/*=============================================================================#
 # Copyright (c) 2009, 2020 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 RInteger32Store extends AbstractIntegerStore
		implements RDataResizeExtension<Integer>, ExternalizableRStore, Externalizable {
	
	
	private int length;
	
	protected int [] intValues;
	
	
	public RInteger32Store() {
		this.length= 0;
		this.intValues= EMPTY_INT_ARRAY;
	}
	
	public RInteger32Store(final int length) {
		this.intValues= new int[length];
		this.length= length;
	}
	
	public RInteger32Store(final int [] values) {
		this.length= values.length;
		this.intValues= values;
	}
	
	public RInteger32Store(final int [] values, final int length) {
		this.length= length;
		this.intValues= values;
	}
	
	public RInteger32Store(final int [] values, final int @Nullable[] naIdxs) {
		this.length= values.length;
		this.intValues= values;
		if (naIdxs != null) {
			for (int i= 0; i < naIdxs.length; i++) {
				this.intValues[naIdxs[i]]= NA_integer_INT;
			}
		}
	}
	
	public RInteger32Store(final int [] values, final boolean @Nullable[] isNAs) {
		this.length= values.length;
		this.intValues= values;
		if (isNAs != null) {
			if (isNAs.length != this.length) {
				throw new IllegalArgumentException();
			}
			for (int i= 0; i < isNAs.length; i++) {
				if (isNAs[i]) {
					this.intValues[i]= NA_integer_INT;
				}
			}
		}
	}
	
	
	public RInteger32Store(final RJIO io, final int length) throws IOException {
		this.length= length;
		this.intValues= io.readIntData(new int[length], length);
	}
	
	@Override
	public void writeExternal(final RJIO io) throws IOException {
		io.writeIntData(this.intValues, this.length);
	}
	
	@Override
	public void readExternal(final ObjectInput in) throws IOException {
		this.length= in.readInt();
		this.intValues= new int[this.length];
		for (int i= 0; i < this.length; i++) {
			this.intValues[i]= in.readInt();
		}
	}
	
	@Override
	public void writeExternal(final ObjectOutput out) throws IOException {
		out.writeInt(this.length);
		for (int i= 0; i < this.length; i++) {
			out.writeInt(this.intValues[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) {
		return (this.intValues[idx] == NA_integer_INT);
	}
	
	@Override
	public boolean isNA(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		return (this.intValues[(int) idx] == NA_integer_INT);
	}
	
	@Override
	public void setNA(final int idx) {
		this.intValues[idx]= NA_integer_INT;
	}
	
	@Override
	public void setNA(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		this.intValues[(int) idx]= NA_integer_INT;
	}
	
	@Override
	public boolean isMissing(final int idx) {
		return (this.intValues[idx] == NA_integer_INT);
	}
	
	@Override
	public boolean isMissing(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		return (this.intValues[(int) idx] == NA_integer_INT);
	}
	
	@Override
	public int getInt(final int idx) {
		return this.intValues[idx];
	}
	
	@Override
	public int getInt(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		return this.intValues[(int) idx];
	}
	
	@Override
	public void setInt(final int idx, final int value) {
//		assert (value != NA_integer_INT);
		this.intValues[idx]= value;
	}
	
	@Override
	public void setInt(final long idx, final int value) {
//		assert (value != NA_integer_INT);
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		this.intValues[(int) idx]= value;
	}
	
	
	private void prepareInsert(final int[] idxs) {
		this.intValues= prepareInsert(this.intValues, this.length, idxs);
		this.length+= idxs.length;
	}
	
	public void insertInt(final int idx, final int value) {
//		assert (value != NA_integer_INT);
		prepareInsert(new int[] { idx });
		this.intValues[idx]= value;
	}
	
	@Override
	public void insertNA(final int idx) {
		prepareInsert(new int[] { idx });
		this.intValues[idx]= NA_integer_INT;
	}
	
	@Override
	public void insertNA(final int[] idxs) {
		if (idxs.length == 0) {
			return;
		}
		prepareInsert(idxs);
		for (int idx= 0; idx < idxs.length; idx++) {
			this.intValues[idxs[idx]+idx]= NA_integer_INT;
		}
	}
	
	@Override
	public void remove(final int idx) {
		this.intValues= remove(this.intValues, this.length, new int[] { idx });
		this.length --;
	}
	
	@Override
	public void remove(final int[] idxs) {
		this.intValues= remove(this.intValues, this.length, idxs);
		this.length-= idxs.length;
	}
	
	
	@Override
	public @Nullable Integer get(final int idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		final int v= this.intValues[idx];
		return (v != NA_integer_INT) ?
				Integer.valueOf(v) : null;
	}
	
	@Override
	public @Nullable Integer get(final long idx) {
		if (idx < 0 || idx >= this.length) {
			throw new IndexOutOfBoundsException(Long.toString(idx));
		}
		final int v= this.intValues[(int) idx];
		return (v != NA_integer_INT) ?
				Integer.valueOf(v) : null;
	}
	
	@Override
	public @Nullable Integer [] toArray() {
		final var array= new @Nullable Integer [this.length];
		final int[] ints= this.intValues;
		for (int i= 0; i < array.length; i++) {
			final int v= ints[i];
			if (v != NA_integer_INT) {
				array[i]= Integer.valueOf(v);
			}
		}
		return array;
	}
	
	
	@Override
	public final long indexOfNA(long fromIdx) {
		if (fromIdx >= Integer.MAX_VALUE) {
			return -1;
		}
		if (fromIdx < 0) {
			fromIdx= 0;
		}
		final int l= this.length;
		final int[] ints= this.intValues;
		for (int i= (int) fromIdx; i < l; i++) {
			if (ints[i] == NA_integer_INT) {
				return i;
			}
		}
		return -1;
	}
	
	@Override
	public final long indexOf(final int integer, long fromIdx) {
		if (fromIdx >= Integer.MAX_VALUE
				|| integer == NA_integer_INT ) {
			return -1;
		}
		if (fromIdx < 0) {
			fromIdx= 0;
		}
		final int l= this.length;
		final int[] ints= this.intValues;
		for (int i= (int) fromIdx; i < l; i++) {
			if (ints[i] == integer) {
				return i;
			}
		}
		return -1;
	}
	
	
	public void appendTo(final StringBuilder sb) {
		sb.append('[');
		final int l= this.length;
		if (l > 0) {
			final int[] ints= this.intValues;
			for (int i= 0; i < l; i++) {
				sb.append(ints[i]);
				sb.append(", ");
			}
			sb.delete(sb.length() - 2, sb.length());
		}
		sb.append(']');
	}
	
}
