package com.one.vector;

import java.io.*;

public class ChannelMatrix extends Effect
{
	protected int[][] factors = new int[4][4];
	protected int[] divisors = new int[4];
	protected int[] offsets = new int[4];
	
	protected int[] values = new int[4];
	
	public ChannelMatrix()
	{
		factors[0][0] = 1;
		factors[1][1] = 1;
		factors[2][2] = 1;
		factors[3][3] = 1;
		
		divisors[0] = 1;
		divisors[1] = 1;
		divisors[2] = 1;
		divisors[3] = 1;
	}
	
	public void read(DataInputStream dis) throws IOException
	{
		name = dis.readUTF();
		hidden = dis.readBoolean();
		
		factors[0][0] = dis.readInt();
		factors[0][1] = dis.readInt();
		factors[0][2] = dis.readInt();
		factors[0][3] = dis.readInt();
		factors[1][0] = dis.readInt();
		factors[1][1] = dis.readInt();
		factors[1][2] = dis.readInt();
		factors[1][3] = dis.readInt();
		factors[2][0] = dis.readInt();
		factors[2][1] = dis.readInt();
		factors[2][2] = dis.readInt();
		factors[2][3] = dis.readInt();
		factors[3][0] = dis.readInt();
		factors[3][1] = dis.readInt();
		factors[3][2] = dis.readInt();
		factors[3][3] = dis.readInt();
		
		divisors[0] = dis.readInt();
		divisors[1] = dis.readInt();
		divisors[2] = dis.readInt();
		divisors[3] = dis.readInt();
		
		offsets[0] = dis.readInt();
		offsets[1] = dis.readInt();
		offsets[2] = dis.readInt();
		offsets[3] = dis.readInt();
	}
	
	public void write(DataOutputStream dos) throws IOException
	{
		dos.writeUTF(name);
		dos.writeBoolean(hidden);
		
		dos.writeInt(factors[0][0]);
		dos.writeInt(factors[0][1]);
		dos.writeInt(factors[0][2]);
		dos.writeInt(factors[0][3]);
		dos.writeInt(factors[1][0]);
		dos.writeInt(factors[1][1]);
		dos.writeInt(factors[1][2]);
		dos.writeInt(factors[1][3]);
		dos.writeInt(factors[2][0]);
		dos.writeInt(factors[2][1]);
		dos.writeInt(factors[2][2]);
		dos.writeInt(factors[2][3]);
		dos.writeInt(factors[3][0]);
		dos.writeInt(factors[3][1]);
		dos.writeInt(factors[3][2]);
		dos.writeInt(factors[3][3]);
		
		dos.writeInt(divisors[0]);
		dos.writeInt(divisors[1]);
		dos.writeInt(divisors[2]);
		dos.writeInt(divisors[3]);
		
		dos.writeInt(offsets[0]);
		dos.writeInt(offsets[1]);
		dos.writeInt(offsets[2]);
		dos.writeInt(offsets[3]);
	}
	
	public void apply(int[] rgb, int[] temp, int width, int height)
	{
		if(hidden)
		{
			return;
		}
		
		int a, r, g, b;
		
		for(int i = 0; i < rgb.length; i++)
		{
			a = (rgb[i] >> 24) & 0xFF;
			r = (rgb[i] >> 16) & 0xFF;
			g = (rgb[i] >> 8) & 0xFF;
			b = rgb[i] & 0xFF;
			
			values[0] = (a * factors[0][0] + r * factors[1][0] + g * factors[2][0] + b * factors[3][0]) / divisors[0] + offsets[0];
			values[1] = (a * factors[0][1] + r * factors[1][1] + g * factors[2][1] + b * factors[3][1]) / divisors[1] + offsets[1];
			values[2] = (a * factors[0][2] + r * factors[1][2] + g * factors[2][2] + b * factors[3][2]) / divisors[2] + offsets[2];
			values[3] = (a * factors[0][3] + r * factors[1][3] + g * factors[2][3] + b * factors[3][3]) / divisors[3] + offsets[3];
			
			a = values[0];
			r = values[1];
			g = values[2];
			b = values[3];
			
			if(a < 0)
			{
				a = 0;
			}
			else if(a > 255)
			{
				a = 255;
			}
			
			if(r < 0)
			{
				r = 0;
			}
			else if(r > 255)
			{
				r = 255;
			}
			
			if(g < 0)
			{
				g = 0;
			}
			else if(g > 255)
			{
				g = 255;
			}
			
			if(b < 0)
			{
				b = 0;
			}
			else if(b > 255)
			{
				b = 255;
			}
			
			rgb[i] = (a << 24) | (r << 16) | (g << 8) | b;
		}
	}
	
	public void setFactor(int srcchannel, int dstchannel, int value)
	{
		factors[srcchannel][dstchannel] = value;
	}
	
	public void setDivisor(int dstchannel, int value)
	{
		divisors[dstchannel] = value;
	}
	
	public void setOffset(int dstchannel, int value)
	{
		offsets[dstchannel] = value;
	}
	
	public int getFactor(int srcchannel, int dstchannel)
	{
		return factors[srcchannel][dstchannel];
	}
	
	public int getDivisor(int dstchannel)
	{
		return divisors[dstchannel];
	}
	
	public int getOffset(int dstchannel)
	{
		return offsets[dstchannel];
	}
}