package filemanager;

import com.one.AbstractFont;
import com.one.ExtGraphics;
import javax.microedition.lcdui.*;
import com.vmx.*;

public class ColorSelector extends gkcCanvas implements Runnable
{
	public static class KeyRepeatThread implements Runnable
	{
		protected ColorSelector canvas;
		
		protected Thread thread;
		protected final Object waiter;
		protected boolean isrunning;
		
		protected boolean enabled;
		protected int key;
		
		public KeyRepeatThread(ColorSelector canvas)
		{
			this.canvas = canvas;
			
			waiter = new Object();
			
			thread = new Thread(this, "ColorSelector/KeyRepeat");
			thread.start();
		}
		
		public void start(int key)
		{
			if(isrunning)
			{
				return;
			}
			
			this.key = key;
			
			enabled = true;
			
			synchronized(waiter)
			{
				waiter.notifyAll();
			}
		}
		
		public void stop()
		{
			enabled = false;
			thread.interrupt();
		}
		
		public boolean isRunning()
		{
			return isrunning;
		}
		
		public void run()
		{
			while(true)
			{
				try
				{
					synchronized(waiter)
					{
						isrunning = false;
						waiter.wait();
					}
					
					isrunning = true;
					Thread.sleep(450);
					
					while(enabled)
					{
						canvas.keyPressed(key);
						Thread.yield();
					}
				}
				catch(InterruptedException ie)
				{
				}
			}
		}
	}
	
	protected int CELL;
	
	protected AbstractFont ttlfont, font;
	protected int ttlfnth, fnth;
	
	protected int width, height;
	
	protected int ttlx, ttly, ttlh, ttlw;
	
	protected Image transp;
	protected int linex, linew, lineh;
	protected int[] liney = new int[5];
	protected int cr, cg, cb, ca;
	protected int[] lnr, lng, lnb, lna, lnc;
	protected boolean interactive;
	
	protected String clr;
	protected int clrx, clry;
	
	protected CommandMenu cmenu;
	
	protected final Image offscreen;
	protected ExtGraphics offgraphics;
	
	protected Thread thread;
	protected final Object waiter;
	protected boolean ispainting;
	protected boolean isshown;
	
	protected KeyRepeatThread repthread;

	protected Image background;
	
	public ColorSelector()
	{
		setFullScreenMode(true);
		
		width = getWidth();
		height = getHeight();
		
		offscreen = Image.createImage(width, height);
		offgraphics = new ExtGraphics(offscreen.getGraphics());
		
		ttlfont = AbstractFont.getFont(AbstractFont.FACE_SYSTEM, AbstractFont.STYLE_PLAIN, AbstractFont.SIZE_MEDIUM);
		font = AbstractFont.getFont(AbstractFont.FACE_SYSTEM, AbstractFont.STYLE_PLAIN, options.largeFontInMenu ? AbstractFont.SIZE_MEDIUM : AbstractFont.SIZE_SMALL);
		
		ttlfnth = ttlfont.getHeight();
		fnth = font.getHeight();
		
		ttlw = ttlfont.stringWidth(Locale.getString(this, Locale.COLOR_SELECTOR)) + ttlfnth;
		ttlh = ttlfnth * 3 / 2;
		ttlx = ttlfnth / 2;
		ttly = (ttlh - ttlfnth) / 2;
		
		cmenu = new CommandMenu(getRenderer(), null, width, height, options.largeFontInMenu ? AbstractFont.SIZE_MEDIUM : AbstractFont.SIZE_SMALL, true, false, false, false, false);
		
		lineh = (height - ttlh - cmenu.getSoftHeight() - ttlfnth * 2) / 5;
		CELL = lineh / 4;
		lineh -= lineh % CELL;
		lineh += 2;
		
		linew = width - fnth;
		linew -= linew % CELL;
		linew += 2;
		
		linex = (width - linew) / 2;
		
		liney[0] = ttlh + (height - ttlh - cmenu.getSoftHeight() - (lineh - 1) * 5) / 2;
		liney[1] = liney[0] + lineh - 1;
		liney[2] = liney[1] + lineh - 1;
		liney[3] = liney[2] + lineh - 1;
		liney[4] = liney[3] + lineh - 1;
		
		clrx = linex + fnth / 2;
		clry = liney[4] + (lineh - fnth) / 2;
		
		transp = LineEffect.createCheckedField(-1, 0, linew, lineh, CELL);
		
		lnr = new int[linew];
		lng = new int[linew];
		lnb = new int[linew];
		lna = new int[linew];
		lnc = new int[linew];
		
		interactive = true;
		
		addCommand(new Command(Locale.getString(this, Locale.OK_CMD), Command.OK, 1));
		addCommand(new Command(Locale.getString(this, Locale.PALETTE_CMD), Command.ITEM, 2));
		addCommand(new Command(Locale.getString(this, Locale.CANCEL_CMD), Command.CANCEL, 3));
		
		waiter = new Object();
		
		thread = new Thread(this, "ColorSelector/AsyncPaint");
		thread.start();
		
		repthread = new KeyRepeatThread(this);
	}
	
	public void setInteractive(boolean flag)
	{
		interactive = flag;
		
		if(!interactive)
		{
			createGradientLine(lna, 0, 0, 0, 0, 255, 0, 0, 0);
			createGradientLine(lnr, 0, 0, 0, 0, 0, 255, 0, 0);
			createGradientLine(lng, 0, 0, 0, 0, 0, 0, 255, 0);
			createGradientLine(lnb, 0, 0, 0, 0, 0, 0, 0, 255);
		}
	}
	
	public void setColor(int color)
	{
		ca = (color >> 24) & 0xFF;
		cr = (color >> 16) & 0xFF;
		cg = (color >> 8) & 0xFF;
		cb = color & 0xFF;
		
		startRepaint();
	}
	
	public int getColor()
	{
		return (ca << 24) | (cr << 16) | (cg << 8) | cb;
	}
	
	public void startRepaint()
	{
		synchronized(waiter)
		{
			if(!ispainting)
			{
				waiter.notifyAll();
			}
		}
	}
	
	public void waitForRepaint()
	{
		synchronized(waiter)
		{
			if(ispainting)
			{
				try
				{
					waiter.wait();
				}
				catch(InterruptedException ie)
				{
				}
			}
		}
	}
	
	public void showNotify()
	{
		isshown = true;
		startRepaint();
	}
	
	public void hideNotify()
	{
		isshown = false;
		repthread.stop();
	}
	
	public void paint(ExtGraphics g)
	{
		synchronized(offscreen)
		{
			g.drawImage(offscreen, 0, 0, Graphics.LEFT | Graphics.TOP);
		}
	}
	
	public void run()
	{
		try
		{
			while(true)
			{
				synchronized(waiter)
				{
					ispainting = false;
					
					waiter.notifyAll();
					waiter.wait();
					
					ispainting = true;
				}
				
				createGradientLine(lnc, ca, cr, cg, cb, ca, cr, cg, cb);
				
				if(interactive)
				{
					createGradientLine(lna, 0, cr, cg, cb, 255, cr, cg, cb);
					createGradientLine(lnr, ca, 0, cg, cb, ca, 255, cg, cb);
					createGradientLine(lng, ca, cr, 0, cb, ca, cr, 255, cb);
					createGradientLine(lnb, ca, cr, cg, 0, ca, cr, cg, 255);
				}
				
				clr = Integer.toHexString(getColor()).toUpperCase();
				
				synchronized(offscreen)
				{
					//offgraphics.setColor(ColorScheme.colors[ColorScheme.back1]);
					//offgraphics.fillRect(0, 0, width, height);

					if(background != null)
					{
						offgraphics.drawImage(background, 0, 0, Graphics.LEFT | Graphics.TOP);
					}
					else
					{
						images.drawVGradient(offgraphics, ColorScheme.colors[ColorScheme.back1], ColorScheme.colors[ColorScheme.back2], 0, 0, width, height, options.ditherGradients);
					}
					
					offgraphics.setColor(ColorScheme.colors[ColorScheme.fore]);
					offgraphics.setFont(ttlfont);
					offgraphics.drawString(Locale.getString(this, Locale.COLOR_SELECTOR), ttlx, ttly, Graphics.LEFT | Graphics.TOP);
					
					offgraphics.setColor(ColorScheme.colors[ColorScheme.ltborder]);
					offgraphics.drawLine(0, ttlh, ttlw, ttlh);
					
					offgraphics.setClip(linex, liney[0], linew, (lineh - 1) * 5 + 1);
					
					offgraphics.drawImage(transp, linex + 1, liney[0] + 1, Graphics.LEFT | Graphics.TOP);
					offgraphics.drawImage(transp, linex + 1, liney[1] + 1, Graphics.LEFT | Graphics.TOP);
					offgraphics.drawImage(transp, linex + 1, liney[2] + 1, Graphics.LEFT | Graphics.TOP);
					offgraphics.drawImage(transp, linex + 1, liney[3] + 1, Graphics.LEFT | Graphics.TOP);
					offgraphics.drawImage(transp, linex + 1, liney[4] + 1, Graphics.LEFT | Graphics.TOP);
					
					for(int i = 0; i < lineh; i++)
					{
						offgraphics.drawRGB(lnr, 0, linew, linex, liney[0] + i, linew, 1, interactive);
						offgraphics.drawRGB(lng, 0, linew, linex, liney[1] + i, linew, 1, interactive);
						offgraphics.drawRGB(lnb, 0, linew, linex, liney[2] + i, linew, 1, interactive);
						offgraphics.drawRGB(lna, 0, linew, linex, liney[3] + i, linew, 1, true);
						offgraphics.drawRGB(lnc, 0, linew, linex, liney[4] + i, linew, 1, interactive);
					}
					
					int color = getColor();
					int alpha = ((ca << 16) | (ca << 8) | ca);
					int pos;
					
					offgraphics.setColor(color ^ 0xC0C0C0);
					pos = linex + linew * cr / 256;
					offgraphics.drawLine(pos, liney[0], pos, liney[0] + 3);
					offgraphics.drawLine(pos - 1, liney[0] + 2, pos + 1, liney[0] + 2);
					offgraphics.drawLine(pos - 2, liney[0] + 1, pos + 2, liney[0] + 1);
					offgraphics.drawLine(pos, liney[0] + lineh - 1, pos, liney[0] + lineh - 4);
					offgraphics.drawLine(pos - 1, liney[0] + lineh - 3, pos + 1, liney[0] + lineh - 3);
					offgraphics.drawLine(pos - 2, liney[0] + lineh - 2, pos + 2, liney[0] + lineh - 2);
					
					offgraphics.setColor(color ^ 0xC0C0C0);
					pos = linex + linew * cg / 256;
					offgraphics.drawLine(pos, liney[1], pos, liney[1] + 3);
					offgraphics.drawLine(pos - 1, liney[1] + 2, pos + 1, liney[1] + 2);
					offgraphics.drawLine(pos - 2, liney[1] + 1, pos + 2, liney[1] + 1);
					offgraphics.drawLine(pos, liney[1] + lineh - 1, pos, liney[1] + lineh - 4);
					offgraphics.drawLine(pos - 1, liney[1] + lineh - 3, pos + 1, liney[1] + lineh - 3);
					offgraphics.drawLine(pos - 2, liney[1] + lineh - 2, pos + 2, liney[1] + lineh - 2);
					
					offgraphics.setColor(color ^ 0xC0C0C0);
					pos = linex + linew * cb / 256;
					offgraphics.drawLine(pos, liney[2], pos, liney[2] + 3);
					offgraphics.drawLine(pos - 1, liney[2] + 2, pos + 1, liney[2] + 2);
					offgraphics.drawLine(pos - 2, liney[2] + 1, pos + 2, liney[2] + 1);
					offgraphics.drawLine(pos, liney[2] + lineh - 1, pos, liney[2] + lineh - 4);
					offgraphics.drawLine(pos - 1, liney[2] + lineh - 3, pos + 1, liney[2] + lineh - 3);
					offgraphics.drawLine(pos - 2, liney[2] + lineh - 2, pos + 2, liney[2] + lineh - 2);
					
					offgraphics.setColor(color ^ alpha);
					pos = linex + linew * ca / 256;
					offgraphics.drawLine(pos, liney[3], pos, liney[3] + 3);
					offgraphics.drawLine(pos - 1, liney[3] + 2, pos + 1, liney[3] + 2);
					offgraphics.drawLine(pos - 2, liney[3] + 1, pos + 2, liney[3] + 1);
					offgraphics.drawLine(pos, liney[3] + lineh - 1, pos, liney[3] + lineh - 4);
					offgraphics.drawLine(pos - 1, liney[3] + lineh - 3, pos + 1, liney[3] + lineh - 3);
					offgraphics.drawLine(pos - 2, liney[3] + lineh - 2, pos + 2, liney[3] + lineh - 2);
					
					offgraphics.setFont(font);
					
					if(interactive)
					{
						offgraphics.setColor(color);
						LineEffect.drawTextOutline(offgraphics, clr, clrx, clry, 3);
					}
					
					offgraphics.setColor(color ^ 0xC0C0C0);
					offgraphics.drawString(clr, clrx, clry, Graphics.LEFT | Graphics.TOP);
					
					offgraphics.setColor(ColorScheme.colors[ColorScheme.ltborder]);
					offgraphics.drawRect(linex, liney[0], linew - 1, lineh - 1);
					offgraphics.drawRect(linex, liney[1], linew - 1, lineh - 1);
					offgraphics.drawRect(linex, liney[2], linew - 1, lineh - 1);
					offgraphics.drawRect(linex, liney[3], linew - 1, lineh - 1);
					offgraphics.drawRect(linex, liney[4], linew - 1, lineh - 1);
					
					offgraphics.setClip(0, 0, width, height);
					
					cmenu.paint(offgraphics);
				}
				
				if(isshown)
				{
					repaint();
				}
			}
		}
		catch(InterruptedException ie)
		{
		}
	}
	
	public void addCommand(Command c)
	{
		cmenu.addCommand(c);
	}
	
	public void setCommandListener(CommandListener cl)
	{
		cmenu.setCommandListener(cl);
	}
	
	public void keyPressed(int keyCode)
	{
		keyCode = remapKey(keyCode);

		if(cmenu.keyPressed(keyCode))
		{
			startRepaint();
			return;
		}
		
		repthread.start(keyCode);
		
		if(keyCode == KEY_NUM1 && cr > 0)
		{
			cr--;
		}
		else if(keyCode == KEY_NUM3 && cr < 255)
		{
			cr++;
		}
		else if(keyCode == KEY_NUM4 && cg > 0)
		{
			cg--;
		}
		else if(keyCode == KEY_NUM6 && cg < 255)
		{
			cg++;
		}
		else if(keyCode == KEY_NUM7 && cb > 0)
		{
			cb--;
		}
		else if(keyCode == KEY_NUM9 && cb < 255)
		{
			cb++;
		}
		else if(keyCode == KEY_STAR && ca > 0)
		{
			ca--;
		}
		else if(keyCode == KEY_POUND && ca < 255)
		{
			ca++;
		}
		else if(keyCode == KEY_NUM2)
		{
			cr ^= 0xFF;
		}
		else if(keyCode == KEY_NUM5)
		{
			cg ^= 0xFF;
		}
		else if(keyCode == KEY_NUM8)
		{
			cb ^= 0xFF;
		}
		else if(keyCode == KEY_NUM0)
		{
			ca ^= 0xFF;
		}
		else
		{
			return;
		}
		
		startRepaint();
	}
	
	public void keyReleased(int keyCode)
	{
		keyCode = remapKey(keyCode);

		repthread.stop();
		
		if(cmenu.keyReleased(keyCode))
		{
			startRepaint();
			return;
		}
	}
	
	public void keyRepeated(int keyCode)
	{
		keyCode = remapKey(keyCode);

		if(cmenu.isInMenu())
		{
			keyPressed(keyCode);
		}
	}
	
	public static void createGradientLine(int[] rgb, int sa, int sr, int sg, int sb, int ea, int er, int eg, int eb)
	{
		rgb[0] = (sa << 24) | (sr << 16) | (sg << 8) | sb;
		rgb[rgb.length - 1] = (ea << 24) | (er << 16) | (eg << 8) | eb;
		
		int a, r, g, b;
		int i, j, n;
		
		for(i = 1, n = rgb.length - 2; i <= n; i++)
		{
			j = n - i;
			
			a = (sa * j + ea * i) / n;
			r = (sr * j + er * i) / n;
			g = (sg * j + eg * i) / n;
			b = (sb * j + eb * i) / n;
			
			rgb[i] = (a << 24) | (r << 16) | (g << 8) | b;
		}
	}
}