package com.one.vector;

import java.io.*;

public class Transform
{
	public static final int NORMAL = 0;
	public static final int EXTEND = 1;
	public static final int LOOP = 2;
	public static final int SLIDE = 3;
	public static final int TRIGGER = 4;
	
	protected String name;
	protected ArrayData data;
	protected int param, subparam;
	protected int startframe, endframe;
	protected int preposition, postposition;
	protected int mode;
	protected int length, activelength;
	
	protected int position;
	
	public Transform(ArrayData data, int param, int startframe, int endframe, int mode)
	{
		name = VectorElement.defaultName();
		
		this.data = data;
		this.param = param;
		
		subparam = -1;
		
		setBounds(startframe, endframe);
		setMode(mode);
	}
	
	public Transform(ArrayData data, int param, int startframe, int endframe, int pregap, int postgap, int mode)
	{
		name = VectorElement.defaultName();
		
		this.data = data;
		this.param = param;
		
		subparam = -1;
		
		setBounds(startframe, endframe, pregap, postgap);
		setMode(mode);
	}
	
	public Transform(ArrayData data, int param, int subparam, int startframe, int endframe, int mode)
	{
		name = VectorElement.defaultName();
		
		this.data = data;
		this.param = param;
		this.subparam = subparam;
		
		setBounds(startframe, endframe);
		setMode(mode);
	}
	
	public Transform(ArrayData data, int param, int subparam, int startframe, int endframe, int pregap, int postgap, int mode)
	{
		name = VectorElement.defaultName();
		
		this.data = data;
		this.param = param;
		this.subparam = subparam;
		
		setBounds(startframe, endframe, pregap, postgap);
		setMode(mode);
	}
	
	public Transform(DataInputStream dis) throws IOException
	{
		read(dis);
	}
	
	public int getParam()
	{
		return param;
	}
	
	public int getSubParam()
	{
		return subparam;
	}
	
	public void setFrame(int frame)
	{
		position = frame - startframe;
		
		if(mode == LOOP)
		{
			if(position >= 0)
			{
				position %= length;
			}
		}
		else if(mode == SLIDE)
		{
			if(position >= 0)
			{
				if(position / length % 2 == 0)
				{
					position %= length;
				}
				else
				{
					position = length - position % length;
				}
			}
		}
	}
	
	public boolean isApplied()
	{
		if(mode == EXTEND)
		{
			return true;
		}
		else if(mode == LOOP || mode == SLIDE)
		{
			return position >= preposition && position <= postposition;
		}
		else if(mode == TRIGGER)
		{
			return position == -1 || position == 0;
		}
		else
		{
			return position >= 0 && position <= length;
		}
	}
	
	public double getPosition()
	{
		if(mode == EXTEND)
		{
			return (double)position / (double)length;
		}
		else if(mode == LOOP || mode == SLIDE)
		{
			if(position >= 0)
			{
				if(position < preposition)
				{
					return 0.0f;
				}
				else if(position <= postposition)
				{
					return (double)(position - preposition) / (double)activelength;
				}
				else
				{
					return 1.0f;
				}
			}
			else
			{
				return 0.0f;
			}
		}
		else if(mode == TRIGGER)
		{
			if(position < 0)
			{
				return 0.0f;
			}
			else
			{
				return 1.0f;
			}
		}
		else
		{
			if(position < 0)
			{
				return 0.0f;
			}
			else if(position <= length)
			{
				return (double)position / (double)length;
			}
			else
			{
				return 1.0f;
			}
		}
	}
	
	public ArrayData getData()
	{
		return data;
	}
	
	public void setBounds(int startframe, int endframe)
	{
		this.startframe = startframe;
		this.endframe = endframe;
		
		length = endframe - startframe;
		activelength = length;
		
		preposition = 0;
		postposition = length;
	}
	
	public void setBounds(int startframe, int endframe, int pregap, int postgap)
	{
		this.startframe = startframe;
		this.endframe = endframe;
		
		length = endframe - startframe;
		activelength = length - pregap - postgap;
		
		preposition = pregap;
		postposition = length - postgap;
	}
	
	public int getStartFrame()
	{
		return startframe;
	}
	
	public int getEndFrame()
	{
		return endframe;
	}
	
	public int getPreGap()
	{
		return preposition;
	}
	
	public int getPostGap()
	{
		return length - postposition;
	}
	
	public int getLength()
	{
		return length;
	}
	
	public int getActiveLength()
	{
		return activelength;
	}
	
	public void setMode(int mode)
	{
		this.mode = mode;
	}
	
	public int getMode()
	{
		return mode;
	}
	
	public void setName(String nm)
	{
		if(nm != null)
		{
			name = nm;
		}
		else
		{
			name = VectorElement.defaultName();
		}
	}
	
	public String getName()
	{
		return name;
	}
	
	public void setParam(int param)
	{
		this.param = param;
	}
	
	public void setSubParam(int subparam)
	{
		this.subparam = subparam;
	}
	
	public void read(DataInputStream dis) throws IOException
	{
		name = dis.readUTF();
		
		data = new ArrayData(dis);
		
		param = dis.readInt();
		subparam = dis.readInt();
		
		setBounds(dis.readInt(), dis.readInt(), dis.readInt(), dis.readInt());
		setMode(dis.readUnsignedByte());
	}
	
	public void write(DataOutputStream dos) throws IOException
	{
		dos.writeUTF(name);
		
		data.write(dos);
		
		dos.writeInt(param);
		dos.writeInt(subparam);
		
		dos.writeInt(getStartFrame());
		dos.writeInt(getEndFrame());
		dos.writeInt(getPreGap());
		dos.writeInt(getPostGap());
		
		dos.writeByte(getMode());
	}
}