package charactermanaj.ui.model;

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

import charactermanaj.graphics.filters.ColorConvertParameter;
import charactermanaj.model.ColorGroup;
import charactermanaj.model.ColorInfo;
import charactermanaj.model.Layer;
import charactermanaj.model.PartsColorInfo;
import charactermanaj.model.PartsColorManager;
import charactermanaj.model.PartsIdentifier;
import charactermanaj.ui.ColorDialog;
import charactermanaj.ui.ImageSelectPanel;
import charactermanaj.ui.ImageSelectPanel.ImageSelectPanelEvent;
import charactermanaj.ui.ImageSelectPanel.ImageSelectPanelListener;

public class PartsColorCoordinator {

	private IdentityHashMap<ImageSelectPanel, ColorDialog> colorDialogMap
			= new IdentityHashMap<ImageSelectPanel, ColorDialog>();
	
	private PartsColorManager partsColorMrg;
	
	private ColorGroupCoordinator colorGroupCoordinator;
	
	public PartsColorCoordinator(PartsColorManager partsColorMrg, ColorGroupCoordinator colorGroupCoordinator) {
		if (partsColorMrg == null || colorGroupCoordinator == null) {
			throw new IllegalArgumentException();
		}
		this.partsColorMrg = partsColorMrg;
		this.colorGroupCoordinator = colorGroupCoordinator;
	}
	
	public void register(final ImageSelectPanel imageSelectPanel, final ColorDialog colorDialog) {
		if (imageSelectPanel == null || colorDialog == null) {
			throw new IllegalArgumentException();
		}
		if (colorDialogMap.containsKey(imageSelectPanel)) {
			throw new IllegalArgumentException("already registered: " + imageSelectPanel);
		}
		colorDialogMap.put(imageSelectPanel, colorDialog);
		
		imageSelectPanel.addImageSelectListener(new ImageSelectPanelListener() {
			public void onChangeColor(ImageSelectPanelEvent event) {
				// なにもしない
			}
			public void onPreferences(ImageSelectPanelEvent event) {
				// なにもしない
			}
			public void onChange(ImageSelectPanelEvent event) {
				PartsColorCoordinator.this.loadColorSettingToColorDialog(imageSelectPanel, colorDialog);
			}
			public void onSelectChange(ImageSelectPanelEvent event) {
				PartsColorCoordinator.this.loadColorSettingToColorDialog(imageSelectPanel, colorDialog);
			}
		});
		
		colorDialog.addColorChangeListener(new ColorChangeListener() {
			public void onColorChange(ColorChangeEvent event) {
				saveColorSettingAll();
			}
			public void onColorGroupChange(ColorChangeEvent event) {
				saveColorSettingAll();
			}
		});
	}
	
	protected void loadColorSettingToColorDialog(ImageSelectPanel imageSelectPanel, ColorDialog colorDialog) {
		PartsIdentifier selectedParts = imageSelectPanel.getSelectedPartsIdentifier();
		if (selectedParts == null) {
			return;
		}
		
		colorDialog.setPartsIdentifier(selectedParts);
		PartsColorInfo partsColorInfo = partsColorMrg.getPartsColorInfo(selectedParts, false);
		
		for (Map.Entry<Layer, ColorInfo> entry : partsColorInfo.entrySet()) {
			Layer layer = entry.getKey();
			ColorInfo colorInfo = entry.getValue();
			
			ColorGroup colorGroup = colorInfo.getColorGroup();
			if (colorGroup == null) {
				colorGroup = ColorGroup.NA;
			}
			colorDialog.setColorGroup(layer, colorGroup);
			boolean syncColorGroup = colorInfo.isSyncColorGroup();
			colorDialog.setSyncColorGroup(layer, syncColorGroup);

			ColorConvertParameter param = colorInfo.getColorParameter();
			colorDialog.setColorConvertParameter(layer, param);
			
			if (syncColorGroup) {
				colorGroupCoordinator.syncColorGroup(colorDialog.getPartsCategory(), layer, colorDialog);
			}
		}
	}
	
	protected void saveColorSettingAll() {
		for (Map.Entry<ImageSelectPanel, ColorDialog> entry : colorDialogMap.entrySet()) {
			ImageSelectPanel imageSelectPanel = entry.getKey();
			ColorDialog colorDialog = entry.getValue();
			saveColorSettingFromColorDialog(imageSelectPanel, colorDialog);
		}
	}
	
	protected void saveColorSettingFromColorDialog(ImageSelectPanel imageSelectPanel, ColorDialog colorDialog) {
		PartsIdentifier selectedParts = imageSelectPanel.getSelectedPartsIdentifier();
		if (selectedParts == null) {
			return;
		}

		Map<Layer, ColorConvertParameter> paramMap = colorDialog.getColorConvertParameters();
		
		PartsColorInfo partsColorInfo = partsColorMrg.getPartsColorInfo(selectedParts, true);
		for (Map.Entry<Layer, ColorConvertParameter> entry : paramMap.entrySet()) {
			Layer layer = entry.getKey();
			ColorConvertParameter param = entry.getValue();

			ColorInfo colorInfo = new ColorInfo();
			ColorGroup colorGroup = colorDialog.getColorGroup(layer);
			colorInfo.setColorGroup(colorGroup);
			boolean syncColorGroup = colorDialog.isSyncColorGroup(layer);
			colorInfo.setSyncColorGroup(syncColorGroup);
			colorInfo.setColorParameter(param);
			partsColorInfo.put(layer, colorInfo);
		}
		boolean applyAll = colorDialog.isApplyAll();
		partsColorMrg.setPartsColorInfo(selectedParts, partsColorInfo, applyAll);
	}
	
	public Map<Layer, ColorConvertParameter> getColorConvertParameterMap() {
		final HashMap<Layer, ColorConvertParameter> colorConvertParameterMap = new HashMap<Layer, ColorConvertParameter>();
		for (ColorDialog colorDlg : colorDialogMap.values()) {
			for (Map.Entry<Layer, ColorConvertParameter> entry : colorDlg.getColorConvertParameters().entrySet()) {
				Layer layer = entry.getKey();
				ColorConvertParameter colorConvertParameter = entry.getValue();
				colorConvertParameterMap.put(layer, colorConvertParameter);
			}
		}
		return colorConvertParameterMap;
	}
	
	public void initColorDialog() {
		for (Map.Entry<ImageSelectPanel, ColorDialog> entry : colorDialogMap.entrySet()) {
			ImageSelectPanel imageSelectPanel = entry.getKey();
			ColorDialog colorDialog = entry.getValue();
			PartsIdentifier partsIdentifier = imageSelectPanel.getSelectedPartsIdentifier();
			colorDialog.setPartsIdentifier(partsIdentifier);
			if (partsIdentifier != null) {
				PartsColorInfo partsColorInfo = partsColorMrg.getPartsColorInfo(partsIdentifier, false);
				for (Map.Entry<Layer, ColorInfo> colorInfoEntry : partsColorInfo.entrySet()) {
					Layer layer = colorInfoEntry.getKey();
					ColorInfo colorInfo = colorInfoEntry.getValue();
					colorDialog.setColorGroup(layer, colorInfo.getColorGroup());
					colorDialog.setSyncColorGroup(layer, colorInfo.isSyncColorGroup());
					colorDialog.setColorConvertParameter(layer, colorInfo.getColorParameter());
				}
			}
		}
	}
	
}
