/*
	Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
	и других спецификаций для функционирования компактных приложений на языке
	Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

	Copyright © 2016, 2019 Малик Разработчик

	Это свободная программа: вы можете перераспространять ее и/или изменять
	ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
	в каком она была опубликована Фондом свободного программного обеспечения;
	либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

	Эта программа распространяется в надежде, что она будет полезной,
	но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
	или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
	общественной лицензии GNU.

	Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
	вместе с этой программой. Если это не так, см.
	<https://www.gnu.org/licenses/>.
*/


package malik.emulator.midp;

import java.io.*;
import javax.microedition.lcdui.*;
import malik.emulator.fileformats.graphics.*;
import malik.emulator.fileformats.graphics.pnglib.*;
import malik.emulator.io.cloud.*;
import malik.emulator.media.graphics.*;

final class ImageCommand extends ConsoleCommand
		implements Runnable, CommandListener, ItemCommandListener, ItemStateListener
{
	private static final class SaveThread extends Thread
	{
		private Image image;
		private String fileName;

		SaveThread(Image image, String fileName)
		{
			super("Сохранение изображения…");
			this.image = image;
			this.fileName = fileName;
		}

		public void run()
		{
			String fileName = this.fileName;
			GraphicBuffer buf = this.image.getBuffer();
			ImageEncoder encoder;
			FileOutputStream file;
			try
			{
				System.out.println("Сохранение изображения в файл " + fileName + "…");
				(encoder = new PNGEncoder()).setPixels(true,
						buf.getWidth(), buf.getHeight(), buf.getPixels());
				(file = new FileOutputStream(fileName)).checkOpenError();
				try
				{
					encoder.saveToOutputStream(file);
				}
				finally
				{
					file.close();
				}
				System.out.println("Сохранение изображения в файл " + fileName +
						" успешно завершено.");
			}
			catch(IOException e)
			{
				e.printRealStackTrace();
				System.out.println("Сохранение изображения в файл " + fileName +
						" завершено с ошибками.");
			}
		}
	}


	private boolean terminated;
	private int imageIndex;
	private Image[] allImages;
	private Command commandCancel;
	private Command commandBack;
	private Command commandSaveDialog;
	private Command commandSaveToFile;
	private Gauge itemLoadingProgress;
	private ImageItem itemCurrentImage;
	private Item itemPrevImage;
	private Item itemNextImage;
	private TextField itemFileNamePNG;
	private Alert screenLoading;
	private Form screenImages;
	private Form screenSavePNG;

	ImageCommand()
	{
		super("изображения");
	}

	public void run(String[] arguments)
	{
		terminated = false;
		getItemLoadingProgress().setValue(0);
		MIDletProxy.getInstance().getEmulatorScreen().setCurrent(getScreenLoading());
		(new Thread(this, "Поиск изображений…")).start();
	}

	public void run()
	{
		int i;
		int memoryLength;
		int imagesCount;
		Image[] imagesList;
		Object[] memory;
		Object current;
		Gauge progress;
		ImageItem currentImage;
		if((progress = itemLoadingProgress) == null)
		{
			return;
		}
		memoryLength = (memory = Memory.getAllObjects()).length;
		imagesCount = 0;
		for(i = 0; i < memoryLength; i++)
		{
			if(terminated)
			{
				return;
			}
			if(memory[i] instanceof Image)
			{
				imagesCount++;
			}
			progress.setValue((i << 4) / memoryLength);
		}
		imagesList = new Image[imagesCount];
		imagesCount = 0;
		for(i = 0; i < memoryLength; i++)
		{
			if(terminated)
			{
				return;
			}
			if((current = memory[i]) instanceof Image)
			{
				imagesList[imagesCount] = (Image) current;
				imagesCount++;
			}
			progress.setValue((i << 4) / memoryLength + 0x10);
		}
		progress.setValue(0x20);
		imageIndex = 0;
		allImages = imagesList;
		MIDletProxy.getInstance().getEmulatorScreen().setCurrent(getScreenImages());
		if(imagesCount > 0 && (currentImage = itemCurrentImage) != null)
		{
			currentImage.setImage(imagesList[0]);
		}
	}

	public void commandAction(Command command, Displayable screen)
	{
		int idx;
		Image[] list;
		String fileName;
		Display display = MIDletProxy.getInstance().getEmulatorScreen();
		if(screen == screenLoading && command == commandCancel)
		{
			terminated = true;
			allImages = null;
			commandCancel = null;
			itemLoadingProgress = null;
			screenLoading = null;
			display.setCurrent(getConsoleScreen());
			return;
		}
		if(screen == screenImages)
		{
			if(command == commandSaveDialog && imageIndex < allImages.length)
			{
				display.setCurrent(getScreenSavePNG());
				return;
			}
			if(command == commandBack)
			{
				allImages = null;
				commandCancel = null;
				commandBack = null;
				commandSaveDialog = null;
				commandSaveToFile = null;
				itemLoadingProgress = null;
				itemCurrentImage = null;
				itemPrevImage = null;
				itemNextImage = null;
				itemFileNamePNG = null;
				screenLoading = null;
				screenImages = null;
				screenSavePNG = null;
				display.setCurrent(getConsoleScreen());
			}
			return;
		}
		label0:
		{
			if(screen == screenSavePNG)
			{
				display.setCurrent(getScreenImages());
				if(command == commandSaveToFile)
				{
					fileName = itemFileNamePNG.getString();
					break label0;
				}
			}
			return;
		}
		if((idx = imageIndex) < (list = allImages).length)
		{
			(new SaveThread(list[idx], fileName)).start();
		}
	}

	public void commandAction(Command command, Item item)
	{
		int idx;
		int len;
		Image[] list;
		if(command == List.SELECT_COMMAND && (len = (list = allImages).length) > 0)
		{
			if(item == itemPrevImage)
			{
				imageIndex = idx = (imageIndex + len - 1) % len;
			}
			else if(item == itemNextImage)
			{
				imageIndex = idx = (imageIndex + 1) % len;
			}
			else
			{
				return;
			}
			itemCurrentImage.setImage(list[idx]);
		}
	}

	public void itemStateChanged(Item item)
	{
		String fileName;
		TextField field;
		if(item == (field = itemFileNamePNG))
		{
			if((fileName = field.getString()) != null && fileName.length() <= 0)
			{
				screenSavePNG.removeCommand(commandSaveToFile);
				return;
			}
			screenSavePNG.addCommand(commandSaveToFile);
		}
	}

	private Command getCommandCancel()
	{
		Command result;
		if((result = commandCancel) == null)
		{
			result = commandCancel = new Command("Отмена", Command.CANCEL, 0);
		}
		return result;
	}

	private Command getCommandBack()
	{
		Command result;
		if((result = commandBack) == null)
		{
			result = commandBack = new Command("Назад", Command.BACK, 0);
		}
		return result;
	}

	private Command getCommandSaveDialog()
	{
		Command result;
		if((result = commandSaveDialog) == null)
		{
			result = commandSaveDialog = new Command("Сохранить…", Command.SCREEN, 0);
		}
		return result;
	}

	private Command getCommandSaveToFile()
	{
		Command result;
		if((result = commandSaveToFile) == null)
		{
			result = commandSaveToFile = new Command("Сохранить", Command.OK, 0);
		}
		return result;
	}

	private Gauge getItemLoadingProgress()
	{
		Gauge result;
		if((result = itemLoadingProgress) == null)
		{
			result = itemLoadingProgress = new Gauge(null, false, 0x20, 0);
		}
		return result;
	}

	private Displayable getScreenLoading()
	{
		Alert result;
		if((result = screenLoading) == null)
		{
			result = screenLoading = new Alert("Любите красить пасхальные яйца?", null,
					null, getCommandCancel(), this,
					"Поиск изображений…", null, AlertType.INFO, getItemLoadingProgress());
		}
		return result;
	}

	private Displayable getScreenImages()
	{
		Item[] items;
		Command[] commands;
		Font font;
		Form result;
		if((result = screenImages) == null)
		{
			font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
			items = new Item[] {
					itemCurrentImage = new ImageItem(null, null,
							Item.LAYOUT_CENTER | Item.LAYOUT_NEWLINE_AFTER, null),
					itemPrevImage = new StringItem(Item.LAYOUT_CENTER, -1, -1, null, null,
							List.SELECT_COMMAND, this, "< предыдущее", font, Item.BUTTON),
					itemNextImage = new StringItem(Item.LAYOUT_CENTER, -1, -1, null, null,
							List.SELECT_COMMAND, this, "следующее >", font, Item.BUTTON)
			};
			commands = new Command[] {
					getCommandBack(), getCommandSaveDialog()
			};
			result = screenImages = new Form("Изображения", null,
					commands, this, items, null);
		}
		return result;
	}

	private Displayable getScreenSavePNG()
	{
		Item[] items;
		Command[] commands;
		TextField fileName;
		Form result;
		if((result = screenSavePNG) == null)
		{
			items = new Item[] {
					itemFileNamePNG = fileName = new TextField("Имя файла", "/имя.png", 32,
							Input.ANY)
			};
			commands = new Command[] {
					getCommandSaveToFile(), getCommandBack()
			};
			result = screenSavePNG = new Form("Сохранить", null,
					commands, this, items, this);
			fileName.setPreferredSize(result.getWidth(), -1);
		}
		return result;
	}
}
