/*=============================================================================#
 # Copyright (c) 2009, 2022 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.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

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

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


/**
 * This implementation is limited to length of 2<sup>31</sup>-1.
 */
@NonNullByDefault
public class RNumericB32Store extends AbstractNumericStore
		implements RDataResizeExtension<Double>, ExternalizableRStore, Externalizable {
	
	
	private int length;
	
	protected double [] realValues;
	
	
	public RNumericB32Store() {
		this.length= 0;
		this.realValues= EMPTY_DOUBLE_ARRAY;
	}
	
	public RNumericB32Store(final int length) {
		this.length= length;
		this.realValues= new double[length];
	}
	
	public RNumericB32Store(final double [] values) {
		this.length= values.length;
		this.realValues= values;
	}
	
	public RNumericB32Store(final double []  values, final int @Nullable[] naIdxs) {
		this.length= values.length;
		this.realValues= values;
		if (naIdxs != null) {
			for (int i= 0; i < naIdxs.length; i++) {
				this.realValues[naIdxs[i]]= NA_numeric_DOUBLE;
			}
		}
	}
	
	public RNumericB32Store(final double [] values, final boolean @Nullable[] isNAs) {
		this.length= values.length;
		this.realValues= values;
		if (isNAs != null) {
			if (isNAs.length != this.length) {
				throw new IllegalArgumentException();
			}
			for (int i= 0; i < isNAs.length; i++) {
				if (isNAs[i]) {
					this.realValues[i]= NA_numeric_DOUBLE;
				}
			}
		}
	}
	
	
	public RNumericB32Store(final RJIO io, final int length) throws IOException {
		this.length= length;
		this.realValues= io.readDoubleData(new double[length], length);
	}
	
	@Override
	public void writeExternal(final RJIO io) throws IOException {
		io.writeDoubleData(this.realValues, this.length);
	}
	
	@Override
	public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
		this.length= in.readInt();
		this.realValues= new double[this.length];
		for (int i= 0; i < this.length; i++) {
			this.realValues[i]= Double.longBitsToDouble(in.readLong());
		}
	}
	
	@Override
	public void writeExternal(final ObjectOutput out) throws IOException {
		out.writeInt(this.length);
		for (int i= 0; i < this.length; i++) {
			out.writeLong(Double.doubleToRawLongBits(this.realValues[i]));
		}
	}
	
	
	@Override
	protected final boolean isStructOnly() {
		return false;
	}
	
	
	protected final int length() {
		return this.length;
	}
	
	@Override
	public final long getLength() {
		return this.length;
	}
	
	
	@Override
	public boolean isNA(final int idx) {
		final double v= this.realValues[idx];
		return (Double.isNaN(v)
				&& (int)Double.doubleToRawLongBits(v) == NA_numeric_INT_MATCH);
	}
	
	@Override
	public boolean isNA(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		final double v= this.realValues[(int)idx];
		return (Double.isNaN(v)
				&& (int)Double.doubleToRawLongBits(v) == NA_numeric_INT_MATCH);
	}
	
	@Override
	public void setNA(final int idx) {
		this.realValues[idx]= NA_numeric_DOUBLE;
	}
	
	@Override
	public void setNA(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		this.realValues[(int)idx]= NA_numeric_DOUBLE;
	}
	
	@Override
	public boolean isNaN(final int idx) {
		final double v= this.realValues[idx];
		return (Double.isNaN(v)
				&& (int)Double.doubleToRawLongBits(v) != NA_numeric_INT_MATCH);
	}
	
	@Override
	public boolean isNaN(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		final double v= this.realValues[(int)idx];
		return (Double.isNaN(v)
				&& (int)Double.doubleToRawLongBits(v) != NA_numeric_INT_MATCH);
	}
	
	@Override
	public boolean isMissing(final int idx) {
		return (Double.isNaN(this.realValues[idx]));
	}
	
	@Override
	public boolean isMissing(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		return (Double.isNaN(this.realValues[(int)idx]));
	}
	
	
	@Override
	public double getNum(final int idx) {
		return this.realValues[idx];
	}
	
	@Override
	public double getNum(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		return this.realValues[(int)idx];
	}
	
	@Override
	public void setNum(final int idx, final double value) {
		this.realValues[idx]= (Double.isNaN(value)) ? NaN_numeric_DOUBLE : value;
	}
	
	@Override
	public void setNum(final long idx, final double value) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		this.realValues[(int)idx]= (Double.isNaN(value)) ? NaN_numeric_DOUBLE : value;
	}
	
	
	private void prepareInsert(final int[] idxs) {
		this.realValues= prepareInsert(this.realValues, this.length, idxs);
		this.length+= idxs.length;
	}
	
	public void insertNum(final int idx, final double value) {
		prepareInsert(new int[] { idx });
		this.realValues[idx]= (Double.isNaN(value)) ? NaN_numeric_DOUBLE : value;
	}
	
	@Override
	public void insertNA(final int idx) {
		prepareInsert(new int[] { idx });
		this.realValues[idx]= NA_numeric_DOUBLE;
	}
	
	@Override
	public void insertNA(final int[] idxs) {
		if (idxs.length == 0) {
			return;
		}
		prepareInsert(idxs);
		for (int idx= 0; idx < idxs.length; idx++) {
			this.realValues[idx]= NA_numeric_DOUBLE;
		}
	}
	
	@Override
	public void remove(final int idx) {
		this.realValues= remove(this.realValues, this.length, new int[] { idx });
		this.length--;
	}
	
	@Override
	public void remove(final int[] idxs) {
		this.realValues= remove(this.realValues, this.length, idxs);
		this.length-= idxs.length;
	}
	
	
	@Override
	public Double get(final int idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		final double v= this.realValues[idx];
		return (!Double.isNaN(v)
				|| (int)Double.doubleToRawLongBits(v) != NA_numeric_INT_MATCH) ?
						Double.valueOf(v) : null;
	}
	
	@Override
	public Double get(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		final double v= this.realValues[(int)idx];
		return (!Double.isNaN(v)
				|| (int)Double.doubleToRawLongBits(v) != NA_numeric_INT_MATCH) ?
						Double.valueOf(v) : null;
	}
	
	
	@Override
	public @Nullable Double [] toArray() {
		final var array= new @Nullable Double [this.length];
		final double[] reals= this.realValues;
		for (int i= 0; i < array.length; i++) {
			final double v= reals[i];
			if (!Double.isNaN(v)
					|| (int)Double.doubleToRawLongBits(v) != NA_numeric_INT_MATCH) {
				array[i]= Double.valueOf(v);
			}
		}
		return array;
	}
	
}
