package org.compiere.common;

import java.io.Serializable;
import java.util.ArrayList;

import org.compiere.util.CLoggerSimple;
import org.compiere.util.CompiereLogger;

public class TableModel implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static CompiereLogger	log = new CLoggerSimple(TableModel.class);

	public static interface DirtyListener {
		public void onDirty(boolean dirty);
	}
	private transient DirtyListener dirtyListener = null;
	public static class State {}
	public final static transient State READONLY = new State(){public String toString() {return "READONLY";}};
	public final static transient State UPDATE = new State(){public String toString() {return "UPDATE";}};
	public final static transient State INSERT = new State(){public String toString() {return "INSERT";}};

	/**
	 * @gwt.typeArgs <java.lang.Boolean>
	 */
	protected ArrayList readOnly = new ArrayList(10);
	/**
	 * @gwt.typeArgs <java.lang.String[]>
	 */
	protected ArrayList values = new ArrayList(10);
	protected transient ArrayList states = new ArrayList(10);
	protected transient ArrayList dirty = new ArrayList(10);

	public TableModel() {}
	public String get(int row, int col) {
		if(values.size() > row && row >= 0){
			String[] r = (String[])values.get(row);
			return r[col];
		}else{
			return null;
		}
	}
	public void set(int row, int col, String v) {
		String[] r = (String[])values.get(row);
		r[col] = v;
	}
	public boolean isDirty(int row) {
		if(row < 0)
			return false;
		return ((Boolean)dirty.get(row)).booleanValue(); 
	}

	public void setDirty(int row, boolean flag) {
		log.finest("set row dirty: "+row+" dirty:"+flag);
		//only set dirty flag when flag passed in is not the same
		if(isDirty(row) != flag) {
			dirty.set(row, new Boolean(flag)); 
			if(dirtyListener != null)
				dirtyListener.onDirty(flag);
		}
	}
	public State getRowState(int row) {
		//log.finest("get row state: "+row+"-- "+(State)states.get(row));
		if(states.size() > row  && row >= 0){
			return (State)states.get(row);
		}else{
			return null;
		}
	}
	public void setRowState(int row, State state) {
		log.finest("set row state: "+row+"-- "+state);
		states.set(row, state);
	}

	public String[] getRow(int row) {
		String[] r = (String[])values.get(row);
		return r;
	}
	public void setRow(int row, String[] r) {
		values.set(row, r);
	}

	public void addRow(String r[]) {
		values.add(r);
		//default state is in insert
		states.add(READONLY);
		dirty.add(Boolean.FALSE);
		readOnly.add(Boolean.FALSE);
	}

	public void copyRow(int toRow, int fromRow) {
		String[] from = (String[])values.get(fromRow);
		String[] to = (String[])values.get(toRow);
		for(int i=0; i<from.length; i++)
			to[i] = from[i];
		//default state is in insert
		states.set(toRow, states.get(fromRow));
		dirty.set(toRow, dirty.get(fromRow));
		readOnly.set(toRow, readOnly.get(fromRow));
	}

	public void addRow(int row, String r[]) {
		values.add(row, r);
		//default state is in insert
		states.add(row, READONLY);
		dirty.add(row	, Boolean.FALSE);
		readOnly.add(row, Boolean.FALSE);
	}
	public void removeRow(int row) {
		values.remove(row);
		states.remove(row);
		dirty.remove(row);
		readOnly.remove(row);
	}

	public boolean isEmpty() {
		return values.size() == 0;
	}
	public int rows() {
		return values.size();
	}
	public void resetStates() {
		states = new ArrayList(values.size());
		dirty = new ArrayList(values.size());
		for(int i=0; i<values.size(); i++) {
			states.add(READONLY);
			dirty.add(Boolean.FALSE);
		}
	}
	
	public boolean isReadOnly(int row) {
		return ((Boolean)readOnly.get(row)).booleanValue();
	}
	public void setReadOnly(int row, boolean readonly) {
		readOnly.set(row, new Boolean(readonly));
	}

	public void setDirtyListener(DirtyListener dirtyListener) {
		this.dirtyListener = dirtyListener;
	}
/*	protected int startRow;
	public int startRow() {
		return startRow;
	}
	public int endRow() {
		return startRow+values.size()-1;
	}
	*/
	public boolean nullValue(int row, int col) {
		return (get(row, col) == null);
	}
}
