// Copyright 2009 Konrad Twardowski
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.makagiga.tree;

import static org.makagiga.commons.UI.i18n;

import org.makagiga.Vars;
import org.makagiga.commons.Kiosk;
import org.makagiga.commons.MAction;
import org.makagiga.commons.MArrayList;
import org.makagiga.commons.MDataAction;
import org.makagiga.commons.Property;
import org.makagiga.commons.swing.MButton;
import org.makagiga.commons.swing.MLabel;
import org.makagiga.commons.swing.MMenu;
import org.makagiga.commons.swing.MSettingsPage;
import org.makagiga.fs.MetaInfo;
import org.makagiga.tags.TagsUtils;

/**
 * @since 3.8
 */
public final class TreeSettingsButton extends MButton {
	
	// public
	
	public TreeSettingsButton() {
		super(i18n("Tree Settings"), "ui/tree");
		setPopupMenuEnabled(true);
	}

	// protected

	@Override
	protected MMenu onPopupMenu() {
		MMenu menu = new MMenu();
		menu.addCheckBox(new Action<>(i18n("Small Icons"), Vars.treeSmallIcons, false));
		menu.addCheckBox(new Action<>(i18n("Tool Tips"), Vars.treeToolTips, false));
		
		MMenu thumbnailsMenu = new MMenu(i18n("Thumbnails"), "ui/image");

		thumbnailsMenu.addRadioButton(new Action<>(i18n("No Thumbnails"), Vars.treePreview, true));

		int max = Vars.MAX_TREE_PREVIEW_SIZE / 25;
		for (int i = 0; i < max; i++) {
			int value = i * 25 + Vars.MIN_TREE_PREVIEW_SIZE;
			String name = "- " + value;
			if (value == Vars.MIN_TREE_PREVIEW_SIZE)
				name += (" (" + i18n("Small") + ")");
			else if (value == Vars.treePreviewSize.getDefaultValue())
				name += (" (" + i18n("Default") + ")");
			else if (value == Vars.MAX_TREE_PREVIEW_SIZE)
				name += (" (" + i18n("Large") + ")");
			Action<Integer> a = new Action<>(name, Vars.treePreviewSize, true);
			a.putValue(Action.INT_VALUE, value);
			a.setHelpText(Integer.toString(value));
			thumbnailsMenu.addRadioButton(a, Vars.treePreview.get() && (value == Vars.treePreviewSize.get()));
		}

		thumbnailsMenu.addSeparator();

		thumbnailsMenu.addCheckBox(new Action<>(i18n("Meta Info (image size, etc)"), Vars.treeShowMetaInfo, true))
			.setEnabled(Vars.treePreview.get());

		menu.add(thumbnailsMenu);
		
		menu.addTitle(i18n("Show Properties"));

		menu.addCheckBox(new Action<>(i18n("Categories"), Vars.treeShowCategories, false));
		menu.addCheckBox(new Action<>(i18n("Tags"), Vars.treeShowTags, false, "ui/tags"));
		menu.addCheckBox(new Action<>(i18n("Date Modified"), Vars.treeShowDate, false, "ui/calendar"));
		menu.addCheckBox(new Action<>(i18n("Rating"), Vars.treeShowRating, false, "ui/star"));
		menu.addCheckBox(new Action<>(i18n("Color"), Vars.treeShowColor, false, "ui/color"));

		menu.addSeparator();

		menu.add(new AdvancedAction());

		return menu;
	}
	
	// private

	private static void updateTreeView(final boolean updatePreview) {
		final Tree tree = Tree.getInstance();

		if (updatePreview) {
			tree.invalidatePreview(tree.getModel().getRootItem());
		}

		// save expanded nodes
		final MArrayList<MetaInfo> expanded = new MArrayList<>();
		new Tree.Scanner() {
			@Override
			public void processItem(final MetaInfo item) {
				if (tree.isExpanded(item))
					expanded.add(item);
			}
		};

		tree.getModel().reload();

		// restore expanded nodes
		for (MetaInfo i : expanded)
			tree.setExpanded(i, true);
	}

	// private classes

	private static final class Action<T> extends MDataAction<Property<T>> {

		// private

		private final boolean updatePreview;
		private static final String INT_VALUE = "org.makagiga.tree.TreeSettingsButton$Action.INT_VALUE";

		// public

		@Override
		@SuppressWarnings("unchecked")
		public void onAction() {
			Property<T> property = getData();
			if (property == Vars.treePreview) {
				Vars.treePreview.set(!isEnabled());
			}
			else {
				T value;
				if (Boolean.class.equals(property.getType()))
					value = (T)(Boolean)isSelected();
				else
					value = (T)getValue(INT_VALUE);
				property.set(value);
			}

			if (property == Vars.treePreviewSize)
				Vars.treePreview.yes();

			TreeSettingsButton.updateTreeView(updatePreview);
		}

		// private
		
		private Action(final String name, final Property<T> property, final boolean updatePreview) {
			this(name, property, updatePreview, null);
		}

		private Action(final String name, final Property<T> property, final boolean updatePreview, final String iconName) {
			super(property, name);
			if (iconName != null)
				setSmallIcon(iconName);
			this.updatePreview = updatePreview;

			if (property == Vars.treePreview)
				setSelected(!Vars.treePreview.booleanValue());
			else if (Boolean.class.equals(property.getType()))
				setSelected((Boolean)property.get());
		}

	}

	private static final class AdvancedAction extends MAction {

		// public

		@Override
		public void onAction() {
			if (new AdvancedSettingsPage().exec(getSourceWindow()))
				TreeSettingsButton.updateTreeView(false);
		}

		// private

		private AdvancedAction() {
			super(i18n("Advanced..."));
			setAuthorizationProperty(Kiosk.actionSettings);
		}

	}

	private static final class AdvancedSettingsPage extends MSettingsPage {

		// private

		private AdvancedSettingsPage() {
			super(i18n("Tree"), "ui/tree");
			setName("advanced-tree-settings");

			addSeparator(i18n("General"));
			bind(Vars.treeItemCount, i18n("Show number of items in folder"));
			bind(Vars.treeReopenFiles, i18n("Reopen recent documents on application startup"));

			addSeparator(i18n("System Tags"));
			add(new MLabel("Automatically insert file tags:"));
			for (TagsUtils.AutoTag i : TagsUtils.AutoTag.values())
				bind(i.getProperty(), i.toString());
		}

	}

}
