/*=============================================================================#
 # Copyright (c) 2009, 2021 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.rj.data.impl;

import java.io.IOException;

import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;

import org.eclipse.statet.rj.data.RJIO;
import org.eclipse.statet.rj.data.RLogicalStore;


/**
 * {@link RLogicalStore} supporting long length.
 */
@NonNullByDefault
public class RLogicalByteFix64Store extends AbstractLogicalStore
		implements ExternalizableRStore {
	
	
	public static final byte TRUE= TRUE_BYTE;
	public static final byte FALSE= FALSE_BYTE;
	
	public static final int SEGMENT_LENGTH= DEFAULT_LONG_DATA_SEGMENT_LENGTH;
	
	
	private final long length;
	
	private final byte [] @NonNull[] boolValues;
	
	
	public RLogicalByteFix64Store(final long length) {
		this.length= length;
		this.boolValues= new2dByteArray(length, SEGMENT_LENGTH);
	}
	
	public RLogicalByteFix64Store(final byte [] @NonNull[] values) {
		this.length= check2dArrayLength(values, SEGMENT_LENGTH);
		this.boolValues= values;
	}
	
	public RLogicalByteFix64Store(final boolean [] @NonNull[] values,
			final boolean @Nullable[] @NonNull[] isNAs) {
		this.length= check2dArrayLength(values, SEGMENT_LENGTH);
		this.boolValues= new2dByteArray(this.length, SEGMENT_LENGTH);
		for (int i= 0; i < values.length; i++) {
			final boolean[] sourceValues= values[i];
			final byte[] destValues= this.boolValues[i];
			for (int j= 0; j < sourceValues.length; j++) {
				destValues[j]= (sourceValues[j]) ? TRUE_BYTE : FALSE_BYTE;
			}
		}
		if (isNAs != null) {
			if (check2dArrayLength(isNAs, SEGMENT_LENGTH) != this.length) {
				throw new IllegalArgumentException();
			}
			for (int i= 0; i < isNAs.length; i++) {
				final boolean[] isNAi= isNAs[i];
				for (int j= 0; j < isNAi.length; j++) {
					if (isNAi[j]) {
						this.boolValues[i][j]= NA_logical_BYTE;
					}
				}
			}
		}
	}
	
	
	public RLogicalByteFix64Store(final RJIO io, final long length) throws IOException {
		this.length= length;
		this.boolValues= new2dByteArray(length, SEGMENT_LENGTH);
		for (int i= 0; i < this.boolValues.length; i++) {
			io.readByteData(this.boolValues[i], this.boolValues[i].length);
		}
	}
	
	@Override
	public void writeExternal(final RJIO io) throws IOException {
		for (int i= 0; i < this.boolValues.length; i++) {
			io.writeByteData(this.boolValues[i], this.boolValues[i].length);
		}
	}
	
	
	@Override
	protected final boolean isStructOnly() {
		return false;
	}
	
	
	@Override
	public final long getLength() {
		return this.length;
	}
	
	
	@Override
	public boolean isNA(final int idx) {
		return (this.boolValues[idx / SEGMENT_LENGTH][idx % SEGMENT_LENGTH] == NA_logical_BYTE);
	}
	
	@Override
	public boolean isNA(final long idx) {
		return (this.boolValues[(int)(idx / SEGMENT_LENGTH)][(int)(idx % SEGMENT_LENGTH)] == NA_logical_BYTE);
	}
	
	@Override
	public boolean isMissing(final int idx) {
		return (this.boolValues[idx / SEGMENT_LENGTH][idx % SEGMENT_LENGTH] == NA_logical_BYTE);
	}
	
	@Override
	public boolean isMissing(final long idx) {
		return (this.boolValues[(int)(idx / SEGMENT_LENGTH)][(int)(idx % SEGMENT_LENGTH)] == NA_logical_BYTE);
	}
	
	@Override
	public void setNA(final int idx) {
		this.boolValues[idx / SEGMENT_LENGTH][idx % SEGMENT_LENGTH] =
				NA_logical_BYTE;
	}
	
	@Override
	public void setNA(final long idx) {
		this.boolValues[(int)(idx / SEGMENT_LENGTH)][(int)(idx % SEGMENT_LENGTH)] =
				NA_logical_BYTE;
	}
	
	
	@Override
	public boolean getLogi(final int idx) {
		return (this.boolValues[idx / SEGMENT_LENGTH][idx % SEGMENT_LENGTH] == TRUE_BYTE);
	}
	
	@Override
	public boolean getLogi(final long idx) {
		return (this.boolValues[(int)(idx / SEGMENT_LENGTH)][(int)(idx % SEGMENT_LENGTH)] == TRUE_BYTE);
	}
	
	@Override
	public void setLogi(final int idx, final boolean value) {
		this.boolValues[idx / SEGMENT_LENGTH][idx % SEGMENT_LENGTH] =
				(value) ? TRUE_BYTE : FALSE_BYTE;
	}
	
	@Override
	public void setLogi(final long idx, final boolean value) {
		this.boolValues[(int)(idx / SEGMENT_LENGTH)][(int)(idx % SEGMENT_LENGTH)] =
				(value) ? TRUE_BYTE : FALSE_BYTE;
	}
	
	
	@Override
	public @Nullable Boolean get(final int idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		switch(this.boolValues[idx / SEGMENT_LENGTH][idx % SEGMENT_LENGTH]) {
		case TRUE_BYTE:
			return Boolean.TRUE;
		case FALSE_BYTE:
			return Boolean.FALSE;
		default:
			return null;
		}
	}
	
	@Override
	public @Nullable Boolean get(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		switch(this.boolValues[(int)(idx / SEGMENT_LENGTH)][(int)(idx % SEGMENT_LENGTH)]) {
		case TRUE_BYTE:
			return Boolean.TRUE;
		case FALSE_BYTE:
			return Boolean.FALSE;
		default:
			return null;
		}
	}
	
	@Override
	public @Nullable Boolean [] toArray() {
		final int l= checkToArrayLength();
		final var array= new @Nullable Boolean [l];
		for (int i= 0, destIdx= 0; i < this.boolValues.length; i++) {
			final byte[] bools= this.boolValues[i];
			for (int j= 0; j < bools.length; j++, destIdx++) {
				switch(bools[j]) {
				case TRUE_BYTE:
					array[destIdx]= Boolean.TRUE;
					continue;
				case FALSE_BYTE:
					array[destIdx]= Boolean.FALSE;
					continue;
				default:
					continue;
				}
			}
		}
		return array;
	}
	
	
	@Override
	public long indexOfNA(long fromIdx) {
		if (fromIdx < 0) {
			fromIdx= 0;
		}
		int i= (int)(fromIdx / SEGMENT_LENGTH);
		int j= (int)(fromIdx % SEGMENT_LENGTH);
		{	while (i < this.boolValues.length) {
				final byte[] bools= this.boolValues[i];
				while (j < bools.length) {
					if (bools[i] == NA_logical_BYTE) {
						return (i * (long)SEGMENT_LENGTH) + j;
					}
				}
				i++;
				j= 0;
			}
		}
		return -1;
	}
	
	@Override
	public long indexOf(final int integer, long fromIdx) {
		if (integer == NA_integer_INT ) {
			return -1;
		}
		if (fromIdx < 0) {
			fromIdx= 0;
		}
		int i= (int)(fromIdx / SEGMENT_LENGTH);
		int j= (int)(fromIdx % SEGMENT_LENGTH);
		if (integer != 0) {
			while (i < this.boolValues.length) {
				final byte[] bools= this.boolValues[i];
				while (j < bools.length) {
					if (bools[i] == TRUE_BYTE) {
						return (i * (long)SEGMENT_LENGTH) + j;
					}
				}
				i++;
				j= 0;
			}
		}
		else {
			while (i < this.boolValues.length) {
				final byte[] bools= this.boolValues[i];
				while (j < bools.length) {
					if (bools[i] == FALSE_BYTE) {
						return (i * (long)SEGMENT_LENGTH) + j;
					}
				}
				i++;
				j= 0;
			}
		}
		return -1;
	}
	
}
