package filemanager;

import com.one.AbstractFont;
import com.one.ErrScreen;
import com.one.ExtGraphics;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.rms.*;
import java.io.*;
import com.one.ImageProcessor;
import com.one.IniFile;
import com.one.IniRecord;
import com.one.PNGFile;
import com.one.ProgressBar;
import com.vmx.AuxClass;
import com.vmx.InputStreamDecoder;
import com.vmx.ProgressCallback;
import com.vmx.gkcCanvas;

public class images
{
	public static final int STORE_VERSION = 13;

	public static final int STORE_MODE = PNGFile.TRUECOLOR_ALPHA;
	public static final int STORE_FILTER = PNGFile.FILTER_NONE;

	public static final int FP_SHIFT = 16;
	
	public static final int iFile			= 0,
							iFolder 		= 1,
							iHiddenFolder	= 2,
							iDisk 			= 3,
							iFavorites 		= 4,
							iUp 			= 5,
							iClipboard 		= 6,
							iSieFM 			= 7,
							iCopy 			= 8,
							iMove 			= 9,
							iPaste 			= 10,
							iProperties 	= 11,
							iOptions 		= 12,
							iRename 		= 13,
							iHelp 			= 14,
							iDelete 		= 15,
							iExit 			= 16,
							iNext 			= 17,
							iUnpack 		= 18,
							iMark 			= 19,
							iMarkAll 		= 20,
							iDemarkAll 		= 21,
							iNoMute 		= 22,
							iMute 			= 23,
							iSelect 		= 24,
							iMoveIt 		= 25,
							iPack 			= 26,
							iKey 			= 27,
							iMenu 			= 28,
							iSearch			= 29,
							iMinimize		= 30,
							iCrypt			= 31;
	
	public static final int iconsCount = 32;

	public static final int[] TEST_COLORS =
	{
		0xFFC0C0C0,
		0xFFC0C000,
		0xFF00C0C0,
		0xFF00C000,
		0xFFC000C0,
		0xFFC00000,
		0xFF0000C0,
		0xFF000000
	};
	
	public static int cPlayTitle	= 0xFFFFFFFF,
					  cPlayFore1	= 0xFF800000,
					  cPlayFore2	= 0xFF000080,
					  cImgBack		= 0xFF000000,
					  cVisArrowCap	= 0xFF000080,
                      cVisArrowLine = 0xFFEFEFFF,
					  cVisBack1		= 0xFFD0D0E0,
					  cVisBack2		= 0xFFB0B0C0;
	
	public static int iconWidth			= 16,
	                  iconHeight		= 16,
	                  origIconWidth		= 16,
	                  origIconHeight	= 16,
	                  uiTopHeight		= 20,
	                  uiBottomHeight	= 28,
	                  uiWidth			= 25,
	                  uiTopHSpace		= 6,
	                  uiTopVSpace		= 0,
	                  uiBottomHOffset	= 7,
	                  uiBottomVOffset	= 2,
	                  uiBottomVSpace	= 0,
	                  btnX				= 28,
	                  btnY				= 22,
	                  btnWidth			= 23,
	                  btnHeight			= 23,
	                  playAnimWidth		= 101,
	                  playAnimHeight	= 36,
	                  playAnimFrames	= 4,
	                  waitAnimWidth		= 32,
	                  waitAnimHeight	= 32,
	                  waitAnimFrames	= 4;
	
	public static Image splashBack, playerUI, minUI, buttons, waitAnim;
	public static Image mb_information, mb_question, mb_exclamation, mb_critical;
	
	protected static Image[] iconsExplode;

//	protected static int[] alphaline;
		
	/**
	 * Загрузка картинок в статические поля
	 */
	public static void loadImages(boolean noEffects)
	{
		try
		{
			InputStreamDecoder isd = InputStreamDecoder.getResourceDecoder("/img/layout.ini");
			IniFile ini = new IniFile(isd, true);
			isd.close();

			cPlayTitle		= AuxClass.parseHexInt(ini.getRecord("Colors", "cPlayTitle"		),	cPlayTitle		);
			cPlayFore1		= AuxClass.parseHexInt(ini.getRecord("Colors", "cPlayFore1"		),	cPlayFore1		);
			cPlayFore2		= AuxClass.parseHexInt(ini.getRecord("Colors", "cPlayFore2"		),	cPlayFore2		);
			cImgBack		= AuxClass.parseHexInt(ini.getRecord("Colors", "cImgBack"		),	cImgBack		);
			cVisArrowCap	= AuxClass.parseHexInt(ini.getRecord("Colors", "cVisArrowCap"	),	cVisArrowCap	);
			cVisArrowLine	= AuxClass.parseHexInt(ini.getRecord("Colors", "cVisArrowLine"	),	cVisArrowLine	);
			cVisBack1		= AuxClass.parseHexInt(ini.getRecord("Colors", "cVisBack1"		),	cVisBack1		);
			cVisBack2		= AuxClass.parseHexInt(ini.getRecord("Colors", "cVisBack2"		),	cVisBack2		);

			origIconWidth	= AuxClass.parseInt(ini.getRecord("Positions", "iconWidth"			),	origIconWidth	);
			origIconHeight	= AuxClass.parseInt(ini.getRecord("Positions", "iconHeight"			),	origIconHeight	);
			uiTopHeight		= AuxClass.parseInt(ini.getRecord("Positions", "uiTopHeight"		),	uiTopHeight		);
			uiBottomHeight	= AuxClass.parseInt(ini.getRecord("Positions", "uiBottomHeight"		),	uiBottomHeight	);
			uiTopHSpace		= AuxClass.parseInt(ini.getRecord("Positions", "uiTopHSpace"		),	uiTopHSpace		);
			uiTopVSpace		= AuxClass.parseInt(ini.getRecord("Positions", "uiTopVSpace"		),	uiTopVSpace		);
			uiBottomHOffset	= AuxClass.parseInt(ini.getRecord("Positions", "uiBottomHOffset"	),	uiBottomHOffset	);
			uiBottomVOffset	= AuxClass.parseInt(ini.getRecord("Positions", "uiBottomVOffset"	),	uiBottomVOffset	);
			uiBottomVSpace	= AuxClass.parseInt(ini.getRecord("Positions", "uiBottomVSpace"		),	uiBottomVSpace	);
			btnX			= AuxClass.parseInt(ini.getRecord("Positions", "btnX"				),	btnX			);
			btnY			= AuxClass.parseInt(ini.getRecord("Positions", "btnY"				),	btnY			);
			btnWidth		= AuxClass.parseInt(ini.getRecord("Positions", "btnWidth"			),	btnWidth		);
			btnHeight		= AuxClass.parseInt(ini.getRecord("Positions", "btnHeight"			),	btnHeight		);
			playAnimWidth	= AuxClass.parseInt(ini.getRecord("Positions", "playAnimWidth"		),	playAnimWidth	);
			playAnimHeight	= AuxClass.parseInt(ini.getRecord("Positions", "playAnimHeight"		),	playAnimHeight	);
			playAnimFrames	= AuxClass.parseInt(ini.getRecord("Positions", "playAnimFrames"		),	playAnimFrames	);
			waitAnimWidth	= AuxClass.parseInt(ini.getRecord("Positions", "waitAnimWidth"		),	waitAnimWidth	);
			waitAnimHeight	= AuxClass.parseInt(ini.getRecord("Positions", "waitAnimHeight"		),	waitAnimHeight	);
			waitAnimFrames	= AuxClass.parseInt(ini.getRecord("Positions", "waitAnimFrames"		),	waitAnimFrames	);
		}
		catch(IOException e)
		{
			System.out.println("External layout not loaded: " + e.toString());
		}
		
		iconsExplode = new Image[iconsCount];
		
		gkcCanvas.getRenderer().setFullScreenMode(true);
		int width = gkcCanvas.getDisplayWidth();
		int height = gkcCanvas.getDisplayHeight();

//		alphaline = new int[Math.max(width, height)];

		ProgressCallback callback = ProgressBar.getProgressCallback();

		if(!loadScaledImages(width, height))
		{
			callback.setProgress(0);
			callback.setMax(8);
			callback.setText("Preparing UI for " + width + "x" + height + " display, this may take several minutes...");
			ProgressBar.show();
			
			try
			{
				Image img = Image.createImage("/img/player_ui.png");
				callback.progress(1);
				
				int imgWidth = img.getWidth();
				int imgHeight = img.getHeight();
				
				int topFH = AbstractFont.getFont(AbstractFont.FACE_SYSTEM, AbstractFont.STYLE_BOLD, AbstractFont.SIZE_SMALL).getHeight();
				int bottomFH = AbstractFont.getFont(AbstractFont.FACE_SYSTEM, AbstractFont.STYLE_PLAIN, AbstractFont.SIZE_SMALL).getHeight();
				
				int newHeight = Math.max(imgHeight * (topFH + uiTopVSpace * 2) / uiTopHeight, imgHeight * (bottomFH * 2 + uiBottomVSpace * 3) / uiBottomHeight);
				int newWidth = imgWidth * newHeight / imgHeight;
				
				newWidth += 6 - newWidth % 6;
				newHeight = imgHeight * newWidth / imgWidth;
				
				if(newWidth < imgWidth || newHeight < imgHeight)
				{
					newWidth = imgWidth;
					newHeight = imgHeight;
				}
				
				img = ImageProcessor.scaleImage(img, newWidth, newHeight, true, false);
				callback.progress(1);
				
				uiWidth = newWidth / 6;
				uiTopHeight = (uiTopHeight * newHeight + imgHeight / 2) / imgHeight;
				uiBottomHeight = newHeight - uiTopHeight;
				
				uiTopVSpace = (uiTopHeight - topFH) / 2;
				uiBottomVSpace = (uiBottomHeight - bottomFH * 2) / 3;
				
				uiTopHSpace = (uiTopHSpace * newHeight + imgHeight / 2) / imgHeight;
				uiBottomHOffset = uiBottomHOffset * newHeight / imgHeight;
				uiBottomVOffset = uiBottomVOffset * newHeight / imgHeight;
				
				playerUI = Image.createImage(width, height);
				minUI = Image.createImage(width, uiBottomHeight);
				
				Graphics pgraphics = playerUI.getGraphics();
				Graphics mgraphics = minUI.getGraphics();
				
				pgraphics.setColor(cImgBack);
				pgraphics.fillRect(0, 0, width, height);
				
				mgraphics.setColor(cImgBack);
				mgraphics.fillRect(0, 0, width, uiBottomHeight);
				callback.progress(1);

				if(!noEffects)
				{
					pgraphics.drawImage(ImageProcessor.scaleImage(Image.createImage("/img/player_bg.png"), width, height - uiTopHeight - uiBottomHeight - 1, true, false), 0, uiTopHeight, Graphics.LEFT | Graphics.TOP);
				}
				else
				{
					images.drawVGradient(new ExtGraphics(pgraphics), cVisBack2, cVisBack1, 0, uiTopHeight, width, height - uiTopHeight - uiBottomHeight - 1, true);
				}
				callback.progress(1);
				
				pgraphics.drawRegion(img, 0, 0, uiWidth, uiTopHeight, Sprite.TRANS_NONE, 0, 0, Graphics.LEFT | Graphics.TOP);
				pgraphics.drawRegion(img, 0, uiTopHeight, uiWidth, uiBottomHeight, Sprite.TRANS_NONE, 0, height - uiBottomHeight, Graphics.LEFT | Graphics.TOP);
				mgraphics.drawRegion(img, 0, uiTopHeight, uiWidth, uiBottomHeight, Sprite.TRANS_NONE, 0, 0, Graphics.LEFT | Graphics.TOP);
				
				for(int x = uiWidth; x <= width - uiWidth; x += uiWidth)
				{
					pgraphics.drawRegion(img, uiWidth * 4, 0, uiWidth, uiTopHeight, Sprite.TRANS_NONE, x, 0, Graphics.LEFT | Graphics.TOP);
					pgraphics.drawRegion(img, uiWidth * 4, uiTopHeight, uiWidth, uiBottomHeight, Sprite.TRANS_NONE, x, height - uiBottomHeight, Graphics.LEFT | Graphics.TOP);
					mgraphics.drawRegion(img, uiWidth * 4, uiTopHeight, uiWidth, uiBottomHeight, Sprite.TRANS_NONE, x, 0, Graphics.LEFT | Graphics.TOP);
				}
				
				pgraphics.drawRegion(img, uiWidth * 5, 0, uiWidth, uiTopHeight, Sprite.TRANS_NONE, width - uiWidth, 0, Graphics.LEFT | Graphics.TOP);
				pgraphics.drawRegion(img, uiWidth * 5, uiTopHeight, uiWidth, uiBottomHeight, Sprite.TRANS_NONE, width - uiWidth, height - uiBottomHeight, Graphics.LEFT | Graphics.TOP);
				mgraphics.drawRegion(img, uiWidth * 5, uiTopHeight, uiWidth, uiBottomHeight, Sprite.TRANS_NONE, width - uiWidth, 0, Graphics.LEFT | Graphics.TOP);
				
				btnX = (btnX * newHeight + imgHeight / 2) / imgHeight;
				btnY = (btnY * newHeight + imgHeight / 2) / imgHeight;
				btnWidth = (btnWidth * newHeight + imgHeight / 2) / imgHeight;
				btnHeight = (btnHeight * newHeight + imgHeight / 2) / imgHeight;
				
				/*
				buttons = new Image[3];
				buttons[0] = Image.createImage(img, btnX, btnY, btnWidth, btnHeight, Sprite.TRANS_NONE);
				buttons[1] = Image.createImage(img, btnX + btnWidth, btnY, btnWidth, btnHeight, Sprite.TRANS_NONE);
				buttons[2] = Image.createImage(img, btnX + btnWidth * 2, btnY, btnWidth, btnHeight, Sprite.TRANS_NONE);
				*/
				
				buttons = Image.createImage(img, btnX, btnY, btnWidth * 3, btnHeight, Sprite.TRANS_NONE);
				
				//playAnim = Image.createImage("/img/play.png");
				
				playAnimWidth = width * 3 / 4;
				playAnimHeight = playAnimWidth * 36 / 101; // playAnim.getHeight() * playAnimWidth / playAnim.getWidth();
				
//				if(playAnimWidth < playAnim.getWidth() || playAnimHeight < playAnim.getHeight())
//				{
//					playAnimWidth = playAnim.getWidth();
//					playAnimHeight = playAnim.getHeight();
//				}
				
				//playAnim = ImageProcessor.scaleImage(playAnim, playAnimWidth, playAnimHeight, true);

				playAnimFrames = 1;
				playAnimHeight /= playAnimFrames;

				callback.progress(1);
			}
			catch(Exception e)
			{
				callback.setProgress(5);
			}

			if(true) // !noEffects)
			{
				try
				{
					waitAnim = Image.createImage("/img/wait.png");

					waitAnimWidth = waitAnim.getWidth() / waitAnimFrames;
					waitAnimHeight = waitAnim.getHeight();
				}
				catch(Exception e)
				{
				}
			}
			callback.progress(1);

			if(!noEffects)
			{
				try
				{
					splashBack = ImageProcessor.scaleImage(Image.createImage("/img/splash.png"), width, height, true, false);
				}
				catch(Exception e)
				{
				}
			}
			callback.progress(1);

			if(!noEffects)
			{
				try
				{
					mb_information = Image.createImage("/img/mb_information.png");
					mb_question = Image.createImage("/img/mb_question.png");
					mb_exclamation = Image.createImage("/img/mb_exclamation.png");
					mb_critical = Image.createImage("/img/mb_critical.png");
				}
				catch(Exception e)
				{
				}
			}
			callback.progress(1);
			
			saveScaledImages(width, height, callback);

			ProgressBar.hide();
		}
	}

	public static void loadIcons(ProgressCallback callback, boolean noEffects)
	{
		if(false) // noEffects)
		{
			iconWidth = origIconWidth;
			iconHeight = origIconHeight;
		}
		else
		{
			iconHeight = AbstractFont.getDefaultFont().getHeight();
			iconWidth = (origIconWidth * iconHeight + origIconHeight / 2) / origIconHeight;
		}

		if(!loadScaledIcons())
		{
//			if(!noEffects)
//			{
//				System.out.println("Rescaling icons from " + origIconWidth + "x" + origIconHeight + " to " + iconWidth + "x" + iconHeight);
//			}
			
			try
			{
				InputStreamDecoder ini = InputStreamDecoder.getResourceDecoder("/img/icons.ini");
				loadIcons(ini, callback, noEffects);
				ini.close();
			}
			catch(Exception e)
			{
			}
		}
	}
	
	public static void loadIcons(InputStreamDecoder ini, ProgressCallback callback, boolean noEffects)
	{
		callback.setProgress(0);
		callback.setMax(iconsCount * 2);

		IniRecord record = null;
		Image icon;

		while((record = IniRecord.getNextRecord(ini)) != null)
		{
			try
			{
				icon = ImageProcessor.getImage("/img/", record.value);

				if(true) // !noEffects)
				{
					icon = ImageProcessor.scaleImage(icon, -1, iconHeight, !noEffects, true);
				}

				iconsExplode[Integer.parseInt(record.key)] = icon;
				callback.progress(1);
			}
			catch(Exception e)
			{
				System.out.println("Failed to load icon: " + record.key + " = " + record.value);
			}
		}

		saveScaledIcons(callback);
	}

	public static boolean isTransformLandscape(int transform)
	{
		return transform == Sprite.TRANS_ROT90 ||
			   transform == Sprite.TRANS_ROT270 ||
			   transform == Sprite.TRANS_MIRROR_ROT90 ||
			   transform == Sprite.TRANS_MIRROR_ROT270;
	}

//	public static void drawVAlphaLine(ExtGraphics g, int color, int x, int y, int height)
//	{
//		for(int i = 0; i < height; i++)
//		{
//			alphaline[i] = color;
//		}
//
//		g.drawRGB(alphaline, 0, 1, x, y, 1, height, true);
//	}
//
//	public static void drawHAlphaLine(ExtGraphics g, int color, int x, int y, int width)
//	{
//		for(int i = 0; i < width; i++)
//		{
//			alphaline[i] = color;
//		}
//
//		g.drawRGB(alphaline, 0, width, x, y, width, 1, true);
//	}

	public static boolean drawVGradient(ExtGraphics g, int topColor, int bottomColor, int x, int y, int w, int h, boolean dither)
	{
//		if(isColorOpaque(topColor) && isColorOpaque(bottomColor))
//		{
//			alpha = false;
//		}

		if((topColor & 0xFFFFFF) == (bottomColor & 0xFFFFFF)) // && !alpha)
		{
			g.setColor(topColor);
			g.fillRect(x, y, w, h);
			
			return false;
		}
		
		int x2 = x + w - 1;
		int y2 = y + h;

		if(dither)
		{
			int ia = ((topColor >> 24) & 0xFF) << FP_SHIFT;
			int ir = ((topColor >> 16) & 0xFF) << FP_SHIFT;
			int ig = ((topColor >> 8) & 0xFF) << FP_SHIFT;
			int ib = (topColor & 0xFF) << FP_SHIFT;

			int sa = ((((bottomColor >> 24) & 0xFF) << FP_SHIFT) - ia) / h;
			int sr = ((((bottomColor >> 16) & 0xFF) << FP_SHIFT) - ir) / h;
			int sg = ((((bottomColor >> 8) & 0xFF) << FP_SHIFT) - ig) / h;
			int sb = (((bottomColor & 0xFF) << FP_SHIFT) - ib) / h;

			int cr = ir;
			int cg = ig;
			int cb = ib;

			Image image = Image.createImage(1, 1);
			Graphics graphics = image.getGraphics();
			int pixel;

			int dr, dg, db;

//			if(alpha)
//			{
//				for(; y < y2; y++)
//				{
//					pixel[0] = graphics.getDisplayColor(getColor(0, cr >> FP_SHIFT, cg >> FP_SHIFT, cb >> FP_SHIFT));
//
//					dr = (ir - (((pixel[0] >> 16) & 0xFF) << FP_SHIFT));
//					dg = (ig - (((pixel[0] >> 8) & 0xFF) << FP_SHIFT));
//					db = (ib - ((pixel[0] & 0xFF) << FP_SHIFT));
//
//					cr += dr;
//					cg += dg;
//					cb += db;
//
//					drawHAlphaLine(g, getColor(ia >> FP_SHIFT, cr >> FP_SHIFT, cg >> FP_SHIFT, cb >> FP_SHIFT), x, y, w);
//
//					cr += sr;
//					cg += sg;
//					cb += sb;
//
//					ia += sa;
//					ir += sr;
//					ig += sg;
//					ib += sb;
//				}
//			}

			for(; y < y2; y++)
			{
				pixel = graphics.getDisplayColor(getColor(0, cr >> FP_SHIFT, cg >> FP_SHIFT, cb >> FP_SHIFT));

				dr = (ir - (((pixel >> 16) & 0xFF) << FP_SHIFT));
				dg = (ig - (((pixel >> 8) & 0xFF) << FP_SHIFT));
				db = (ib - ((pixel & 0xFF) << FP_SHIFT));

				cr += dr;
				cg += dg;
				cb += db;

				g.setColor(getColor(0, cr >> FP_SHIFT, cg >> FP_SHIFT, cb >> FP_SHIFT));
				g.drawLine(x, y, x2, y);

				cr += sr;
				cg += sg;
				cb += sb;

				ir += sr;
				ig += sg;
				ib += sb;
			}
		}
		else
		{
			int sa = (topColor >> 24) & 0xFF;
			int sr = (topColor >> 16) & 0xFF;
			int sg = (topColor >> 8) & 0xFF;
			int sb = topColor & 0xFF;

			int ea = (bottomColor >> 24) & 0xFF;
			int er = (bottomColor >> 16) & 0xFF;
			int eg = (bottomColor >> 8) & 0xFF;
			int eb = bottomColor & 0xFF;

			int ca, cr, cg, cb;

//			if(alpha)
//			{
//				for(; y < y2; y++)
//				{
//					ca = (sa * (y2 - y) + ea * (h - y2 + y)) / h;
//					cr = (sr * (y2 - y) + er * (h - y2 + y)) / h;
//					cg = (sg * (y2 - y) + eg * (h - y2 + y)) / h;
//					cb = (sb * (y2 - y) + eb * (h - y2 + y)) / h;
//
//					drawHAlphaLine(g, getColor(ca, cr, cg, cb), x, y, w);
//				}
//			}

			for(; y < y2; y++)
			{
				cr = (sr * (y2 - y) + er * (h - y2 + y)) / h;
				cg = (sg * (y2 - y) + eg * (h - y2 + y)) / h;
				cb = (sb * (y2 - y) + eb * (h - y2 + y)) / h;

				g.setColor(cr, cg, cb);
				g.drawLine(x, y, x2, y);
			}
		}

		return false; // alpha;
	}
	
	public static boolean drawHGradient(ExtGraphics g, int leftColor, int rightColor, int x, int y, int w, int h, boolean dither)
	{
//		if(isColorOpaque(leftColor) && isColorOpaque(rightColor))
//		{
//			alpha = false;
//		}

		if((leftColor & 0xFFFFFF) == (rightColor & 0xFFFFFF)) // && !alpha)
		{
			g.setColor(leftColor);
			g.fillRect(x, y, w, h);

			return false;
		}
		
		int x2 = x + w;
		int y2 = y + h - 1;

		if(dither)
		{
			int ia = ((leftColor >> 24) & 0xFF) << FP_SHIFT;
			int ir = ((leftColor >> 16) & 0xFF) << FP_SHIFT;
			int ig = ((leftColor >> 8) & 0xFF) << FP_SHIFT;
			int ib = (leftColor & 0xFF) << FP_SHIFT;

			int sa = ((((rightColor >> 24) & 0xFF) << FP_SHIFT) - ia) / w;
			int sr = ((((rightColor >> 16) & 0xFF) << FP_SHIFT) - ir) / w;
			int sg = ((((rightColor >> 8) & 0xFF) << FP_SHIFT) - ig) / w;
			int sb = (((rightColor & 0xFF) << FP_SHIFT) - ib) / w;

			int cr = ir;
			int cg = ig;
			int cb = ib;

			Image image = Image.createImage(1, 1);
			Graphics graphics = image.getGraphics();
			int pixel;

			int dr, dg, db;

//			if(alpha)
//			{
//				for(; x < x2; x++)
//				{
//					pixel[0] = graphics.getDisplayColor(getColor(0, cr >> FP_SHIFT, cg >> FP_SHIFT, cb >> FP_SHIFT));
//
//					dr = (ir - (((pixel[0] >> 16) & 0xFF) << FP_SHIFT));
//					dg = (ig - (((pixel[0] >> 8) & 0xFF) << FP_SHIFT));
//					db = (ib - ((pixel[0] & 0xFF) << FP_SHIFT));
//
//					cr += dr;
//					cg += dg;
//					cb += db;
//
//					drawVAlphaLine(g, getColor(ia >> FP_SHIFT, cr >> FP_SHIFT, cg >> FP_SHIFT, cb >> FP_SHIFT), x, y, h);
//
//					cr += sr;
//					cg += sg;
//					cb += sb;
//
//					ia += sa;
//					ir += sr;
//					ig += sg;
//					ib += sb;
//				}
//			}

			for(; x < x2; x++)
			{
				pixel = graphics.getDisplayColor(getColor(0, cr >> FP_SHIFT, cg >> FP_SHIFT, cb >> FP_SHIFT));

				dr = (ir - (((pixel >> 16) & 0xFF) << FP_SHIFT));
				dg = (ig - (((pixel >> 8) & 0xFF) << FP_SHIFT));
				db = (ib - ((pixel & 0xFF) << FP_SHIFT));

				cr += dr;
				cg += dg;
				cb += db;

				g.setColor(getColor(0, cr >> FP_SHIFT, cg >> FP_SHIFT, cb >> FP_SHIFT));
				g.drawLine(x, y, x, y2);

				cr += sr;
				cg += sg;
				cb += sb;

				ir += sr;
				ig += sg;
				ib += sb;
			}
		}
		else
		{
			int sa = (leftColor >> 24) & 0xFF;
			int sr = (leftColor >> 16) & 0xFF;
			int sg = (leftColor >> 8) & 0xFF;
			int sb = leftColor & 0xFF;

			int ea = (rightColor >> 24) & 0xFF;
			int er = (rightColor >> 16) & 0xFF;
			int eg = (rightColor >> 8) & 0xFF;
			int eb = rightColor & 0xFF;

			int ca, cr, cg, cb;

//			if(alpha)
//			{
//				for(; x < x2; x++)
//				{
//					ca = (sa * (x2 - x) + ea * (w - x2 + x)) / w;
//					cr = (sr * (x2 - x) + er * (w - x2 + x)) / w;
//					cg = (sg * (x2 - x) + eg * (w - x2 + x)) / w;
//					cb = (sb * (x2 - x) + eb * (w - x2 + x)) / w;
//
//					drawVAlphaLine(g, getColor(ca, cr, cg, cb), x, y, h);
//				}
//			}

				for(; x < x2; x++)
				{
					cr = (sr * (x2 - x) + er * (w - x2 + x)) / w;
					cg = (sg * (x2 - x) + eg * (w - x2 + x)) / w;
					cb = (sb * (x2 - x) + eb * (w - x2 + x)) / w;

					g.setColor(cr, cg, cb);
					g.drawLine(x, y, x, y2);
				}
		}

		return false; // alpha;
	}

    public static void fillVLineRect(ExtGraphics g, int x, int y, int w, int h)
    {
        int ex = x + w - 1;
        int ey = y + h - 1;

        while(x <= ex)
        {
            g.drawLine(x, y, x, ey);
            x += 2;
        }
    }

    public static void fillHLineRect(ExtGraphics g, int x, int y, int w, int h)
    {
        int ex = x + w - 1;
        int ey = y - h + 1;

        while(y >= ey)
        {
            g.drawLine(x, y, ex, y);
            y -= 2;
        }
    }

	public static void drawVColorTest(Graphics g, int x, int y, int w, int h)
	{
		int delta = w / TEST_COLORS.length;

		for(int i = 0; i < TEST_COLORS.length; i++)
		{
			g.setColor(TEST_COLORS[i]);
			g.fillRect(x + i * delta, y, delta, h);
		}
	}

	public static void drawHColorTest(Graphics g, int x, int y, int w, int h)
	{
		int delta = h / TEST_COLORS.length;

		for(int i = 0; i < TEST_COLORS.length; i++)
		{
			g.setColor(TEST_COLORS[i]);
			g.fillRect(x, y + i * delta, w, delta);
		}
	}

	public static boolean isColorOpaque(int color)
	{
		return (color & 0xFF000000) == 0xFF000000;
	}

	public static int getColor(int ca, int cr, int cg, int cb)
	{
		if(ca < 0)
		{
			ca = 0;
		}
		else if(ca > 255)
		{
			ca = 255;
		}

		if(cr < 0)
		{
			cr = 0;
		}
		else if(cr > 255)
		{
			cr = 255;
		}

		if(cg < 0)
		{
			cg = 0;
		}
		else if(cg > 255)
		{
			cg = 255;
		}

		if(cb < 0)
		{
			cb = 0;
		}
		else if(cb > 255)
		{
			cb = 255;
		}

		return (ca << 24) | (cr << 16) | (cg << 8) | cb;
	}

	public static int blendColors(int color1, int color2, int factor, int divisor)
	{
		if(factor == 0)
		{
			return color1;
		}
		else if(factor == divisor)
		{
			return color2;
		}
		else
		{
			int r1 = color1 & 0xFF0000;
			int g1 = color1 & 0xFF00;
			int b1 = color1 & 0xFF;

			int r2 = (((color2 & 0xFF0000) - r1) * factor / divisor & 0xFF0000) + r1;
			int g2 = (((color2 & 0xFF00) - g1) * factor / divisor & 0xFF00) + g1;
			int b2 = ((color2 & 0xFF) - b1) * factor / divisor + b1;

			return r2 | g2 | b2;
		}
	}

	public static Image createColorSample(int color, int width, int height)
	{
		Image image = Image.createImage(width, height);
		Graphics g = image.getGraphics();

		try
		{
			int rgb[] = new int[width * height];

			for(int i = 0; i < rgb.length; i++)
			{
				rgb[i] = color;
			}

			g.setColor(0xFF000000);
			g.fillRect(0, 0, width, height);

			g.setColor(0xFFFFFFFF);
			g.fillRect((width + 1) >> 1, 0, width >> 1, height >> 1);
			g.fillRect(0, (height + 1) >> 1, width >> 1, height >> 1);

			g.drawRGB(rgb, 0, width, 0, 0, width, height, true);
		}
		catch(OutOfMemoryError oome)
		{
			g.setColor(color);
			g.fillRect(0, 0, width, height);
		}

		return image;
	}

	/**
	 * Достать подходящий значок для данного типа сообщения.
	 *
	 * @param type AlertType
	 * @return значок, соответствующий данному AlertType
	 */
	public static Image getAlertIcon(AlertType type)
	{
		if(type == AlertType.INFO)
		{
			return mb_information;
		}
		else if(type == AlertType.CONFIRMATION)
		{
			return mb_question;
		}
		else if(type == AlertType.ALARM ||
		        type == AlertType.WARNING)
		{
			return mb_exclamation;
		}
		else if(type == AlertType.ERROR)
		{
			return mb_critical;
		}
		else
		{
			return null;
		}
	}

	/**
	 * Достать значок и написать на нем что-нибудь.
	 */
	public static Image getIcon(int index, String text, AbstractFont font, int color)
	{
		if(index < 0 || index >= iconsExplode.length)
		{
			return null;
		}

		int width = iconsExplode[index].getWidth();
		int height = iconsExplode[index].getHeight();

		Image image = Image.createImage(width, height);
		ExtGraphics g = new ExtGraphics(image.getGraphics());

		g.setColor(0xFF000000);
		g.fillRect(0, 0, width, height);

		g.setColor(0xFFFFFFFF);
		g.setFont(font);
		g.drawString(text, (width - font.stringWidth(text)) / 2, (height - font.getHeight()) / 2, Graphics.LEFT | Graphics.TOP);

		int[] fore = new int[width * height];
		image.getRGB(fore, 0, width, 0, 0, width, height);

		ImageProcessor.lightAlphaMask(fore, fore);

		int alpha = (color >> 24) & 0xFF;
		color &= 0xFFFFFF;

		if(alpha < 255)
		{
			for(int i = 0; i < fore.length; i++)
			{
				fore[i] = ((((fore[i] >> 24) & 0xFF) * alpha / 255) << 24) | color;
			}
		}
		else
		{
			for(int i = 0; i < fore.length; i++)
			{
				fore[i] = (fore[i] & 0xFF000000) | color;
			}
		}

		int[] back = new int[width * height];
		iconsExplode[index].getRGB(back, 0, width, 0, 0, width, height);

		ImageProcessor.blendImages(back, fore);

		return Image.createRGBImage(back, width, height, true);
	}
	
	/**
	 * Получить иконку с номером index
	 */
	public static Image getIcon(int index)
	{
		if(index < 0 || index >= iconsExplode.length)
		{
			return null;
		}

		return iconsExplode[index];
	}
	
	/**
	 * Нарисовать иконку с номером index на объекте Graphics g
	 * в положении x,y
	 */
	public static void drawIcon(ExtGraphics g, int index, int x, int y)
	{
		Image icon = getIcon(index);
		
		if(icon != null)
		{
			g.drawImage(icon, x, y, Graphics.LEFT | Graphics.TOP);
		}
	}
	
	protected static boolean loadScaledImages(int width, int height)
	{
		try
		{
			RecordStore rs = RecordStore.openRecordStore(AuxClass.getStoreName(4), true);
			
			if(rs.getNumRecords() == 0)
			{
				rs.closeRecordStore();
				return false;
			}
			
			DataInputStream dis = new DataInputStream(new ByteArrayInputStream(rs.getRecord(1)));
			
			if(dis.readInt() != STORE_VERSION ||
			   dis.readInt() != width ||
			   dis.readInt() != height)
			{
				dis.close();
				rs.closeRecordStore();
				
				RecordStore.deleteRecordStore(AuxClass.getStoreName(4));
				
				return false;
			}
			
			iconWidth = dis.readInt();
			iconHeight = dis.readInt();
			origIconWidth = dis.readInt();
			origIconHeight = dis.readInt();
			uiTopHeight = dis.readInt();
			uiBottomHeight = dis.readInt();
			uiWidth = dis.readInt();
			uiTopHSpace = dis.readInt();
			uiTopVSpace = dis.readInt();
			uiBottomHOffset = dis.readInt();
			uiBottomVOffset = dis.readInt();
			uiBottomVSpace = dis.readInt();
			btnX = dis.readInt();
			btnY = dis.readInt();
			btnWidth = dis.readInt();
			btnHeight = dis.readInt();
			playAnimWidth = dis.readInt();
			playAnimHeight = dis.readInt();
			playAnimFrames = dis.readInt();
			waitAnimWidth = dis.readInt();
			waitAnimHeight = dis.readInt();
			waitAnimFrames = dis.readInt();
			
			playerUI = ImageProcessor.readImage(dis);
			minUI = ImageProcessor.readImage(dis);
			buttons = ImageProcessor.readImage(dis);
			waitAnim = ImageProcessor.readImage(dis);
			//playAnim = readImage(dis);
			splashBack = ImageProcessor.readImage(dis);
			
			mb_information = ImageProcessor.readImage(dis);
			mb_question = ImageProcessor.readImage(dis);
			mb_exclamation = ImageProcessor.readImage(dis);
			mb_critical = ImageProcessor.readImage(dis);
			
			dis.close();
			
			rs.closeRecordStore();
			
			return true;
		}
		catch(Throwable e)
		{
			ErrScreen.showErrMsg(106, e);
			return false;
		}
	}
	
	protected static void saveScaledImages(int width, int height, ProgressCallback callback)
	{
		try
		{
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			DataOutputStream dos = new DataOutputStream(baos);
			
			dos.writeInt(STORE_VERSION);
			
			dos.writeInt(width);
			dos.writeInt(height);
			
			dos.writeInt(iconWidth);
			dos.writeInt(iconHeight);
			dos.writeInt(origIconWidth);
			dos.writeInt(origIconHeight);
			dos.writeInt(uiTopHeight);
			dos.writeInt(uiBottomHeight);
			dos.writeInt(uiWidth);
			dos.writeInt(uiTopHSpace);
			dos.writeInt(uiTopVSpace);
			dos.writeInt(uiBottomHOffset);
			dos.writeInt(uiBottomVOffset);
			dos.writeInt(uiBottomVSpace);
			dos.writeInt(btnX);
			dos.writeInt(btnY);
			dos.writeInt(btnWidth);
			dos.writeInt(btnHeight);
			dos.writeInt(playAnimWidth);
			dos.writeInt(playAnimHeight);
			dos.writeInt(playAnimFrames);
			dos.writeInt(waitAnimWidth);
			dos.writeInt(waitAnimHeight);
			dos.writeInt(waitAnimFrames);

			String prefix = callback.getText() + "\n\nWriting image ";
			String suffuix = " / 9...";
			int counter = 1;

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, playerUI, STORE_MODE, STORE_FILTER, callback);

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, minUI, STORE_MODE, STORE_FILTER, callback);

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, buttons, STORE_MODE, STORE_FILTER, callback);

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, waitAnim, STORE_MODE, STORE_FILTER, callback);

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, splashBack, STORE_MODE, STORE_FILTER, callback);

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, mb_information, STORE_MODE, STORE_FILTER, callback);

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, mb_question, STORE_MODE, STORE_FILTER, callback);

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, mb_exclamation, STORE_MODE, STORE_FILTER, callback);

			callback.setText(prefix + Integer.toString(counter++) + suffuix);
			ImageProcessor.writeImage(dos, mb_critical, STORE_MODE, STORE_FILTER, callback);
			
			byte[] data = baos.toByteArray();
			dos.close();
			
			RecordStore rs = RecordStore.openRecordStore(AuxClass.getStoreName(4), true);

			if(rs.getNumRecords() == 0)
			{
				rs.addRecord(data, 0, data.length);
			}
			else
			{
				rs.setRecord(1, data, 0, data.length);
			}
			
			rs.closeRecordStore();
		}
		catch(Throwable e)
		{
			ErrScreen.showErrMsg(107, e);
		}
	}

	protected static boolean loadScaledIcons()
	{
		try
		{
			RecordStore rs = RecordStore.openRecordStore(AuxClass.getStoreName(8), true);

			if(rs.getNumRecords() == 0)
			{
				rs.closeRecordStore();
				return false;
			}

			DataInputStream dis = new DataInputStream(new ByteArrayInputStream(rs.getRecord(1)));
			rs.closeRecordStore();

			if(dis.readInt() != iconHeight)
			{
				dis.close();
				return false;
			}

			for(int i = 0; i < iconsCount; i++)
			{
				iconsExplode[i] = ImageProcessor.readImage(dis);
			}

			dis.close();

			return true;
		}
		catch(Throwable t)
		{
			return false;
		}
	}

	protected static void saveScaledIcons(ProgressCallback callback)
	{
		try
		{
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			DataOutputStream dos = new DataOutputStream(baos);

			dos.writeInt(iconHeight);

			for(int i = 0; i < iconsCount; i++)
			{
				ImageProcessor.writeImage(dos, iconsExplode[i], PNGFile.TRUECOLOR_ALPHA, PNGFile.FILTER_NONE, null);

				if(callback != null)
				{
					callback.progress(1);
				}
			}

			byte[] data = baos.toByteArray();
			dos.close();

			RecordStore rs = RecordStore.openRecordStore(AuxClass.getStoreName(8), true);

			if(rs.getNumRecords() == 0)
			{
				rs.addRecord(data, 0, data.length);
			}
			else
			{
				rs.setRecord(1, data, 0, data.length);
			}

			rs.closeRecordStore();
		}
		catch(Throwable t)
		{
		}
	}
}
