/*
 * Copyright 2014-2015 See AUTHORS file.
 *
 * 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 com.kotcrab.vis.editor.ui.scene.entityproperties.autotable;

import com.artemis.Component;
import com.artemis.Entity;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import com.kotcrab.vis.editor.Editor;
import com.kotcrab.vis.editor.Icons;
import com.kotcrab.vis.editor.module.InjectModule;
import com.kotcrab.vis.editor.module.project.FileAccessModule;
import com.kotcrab.vis.editor.proxy.EntityProxy;
import com.kotcrab.vis.editor.ui.dialog.SelectFileDialog;
import com.kotcrab.vis.editor.util.Holder;
import com.kotcrab.vis.runtime.util.autotable.ATSelectFile;
import com.kotcrab.vis.runtime.util.autotable.ATSelectFileHandler;
import com.kotcrab.vis.ui.widget.Tooltip;
import com.kotcrab.vis.ui.widget.VisImageButton;
import com.kotcrab.vis.ui.widget.VisLabel;
import com.kotcrab.vis.ui.widget.VisTable;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

import static com.kotcrab.vis.editor.util.vis.EntityUtils.getCommonString;

/** @author Kotcrab */
public class SelectFileFragmentProvider extends AutoTableFragmentProvider<ATSelectFile> {
	@InjectModule private FileAccessModule fileAccessModule;

	private ObjectMap<String, ATSelectFileHandlerGroup> handlerGroups = new ObjectMap<>();

	private ObjectMap<Field, SelectFileDialogSet> fileDialogLabels = new ObjectMap<>();

	@Override
	public void createUI (ATSelectFile annotation, Class type, Field field) {
		String fieldName = annotation.fieldName().equals("") ? field.getName() : annotation.fieldName();

		VisLabel fileLabel = new VisLabel();
		fileLabel.setColor(Color.GRAY);
		fileLabel.setEllipsis(true);

		VisImageButton selectFileButton = new VisImageButton(Icons.MORE.drawable());

		VisTable table = new VisTable(true);
		table.add(new VisLabel(fieldName));
		table.add(fileLabel).expandX().fillX();
		table.add(selectFileButton);

		Tooltip tooltip = new Tooltip(fileLabel, "");

		uiTable.add(table).expandX().fillX().row();

		Holder<ATSelectFileHandler> holder = new Holder<>(getHandler(annotation));

		fileDialogLabels.put(field, new SelectFileDialogSet(fileLabel, tooltip, holder.value));

		FileHandle folder = fileAccessModule.getAssetsFolder().child(annotation.relativeFolderPath());

		final SelectFileDialog selectFontDialog = new SelectFileDialog(annotation.extension(), annotation.hideExtension(), folder, file -> {
			for (EntityProxy proxy : properties.getProxies()) {
				for (Entity entity : proxy.getEntities()) {
					holder.value.applyChanges(entity, file);
				}
			}

			properties.getParentTab().dirty();
			properties.selectedEntitiesChanged();
			properties.endSnapshot();
		});

		selectFileButton.addListener(new ChangeListener() {
			@Override
			public void changed (ChangeEvent event, Actor actor) {
				selectFontDialog.rebuildFileList();
				properties.beginSnapshot();
				Editor.instance.getStage().addActor(selectFontDialog.fadeIn());
			}
		});
	}

	private ATSelectFileHandler getHandler (ATSelectFile annotation) {
		try {
			String groupClassName = annotation.handlerGroupClass();

			ATSelectFileHandlerGroup group = handlerGroups.get(groupClassName);

			if (group == null) {
				Class clazz = Class.forName(groupClassName);
				Constructor constructor = clazz.getConstructor();
				try {
					group = (ATSelectFileHandlerGroup) constructor.newInstance();
				} catch (ClassCastException castEx) {
					throw new IllegalStateException("ATSelectFile handler group must be instance of ATSelectFileHandlerGroup", castEx);
				}

				group.setInjector(injector);
				handlerGroups.put(groupClassName, group);
			}

			return group.getByAlias(annotation.handlerAlias());
		} catch (ReflectiveOperationException e) {
			throw new IllegalStateException("AutoTable failed to create ATSelectFile handler for class: " + annotation.handlerGroupClass(), e);
		}
	}

	@Override
	public void updateUIFromEntities (Array<EntityProxy> proxies, Class type, Field field) throws ReflectiveOperationException {
		SelectFileDialogSet set = fileDialogLabels.get(field);
		String path = getCommonString(proxies, "<?>", set.handler::getLabelValue);
		set.fileLabel.setText(path);
		((VisLabel) set.tooltip.getContent()).setText(path);
		set.tooltip.pack();
	}

	@Override
	public void setToEntities (Class type, Field field, Component component) throws ReflectiveOperationException {

	}

	@Override
	public Object getUiByField (Class type, Field field) {
		return fileDialogLabels.get(field);
	}

	private static class SelectFileDialogSet {
		public VisLabel fileLabel;
		public Tooltip tooltip;
		public ATSelectFileHandler handler;

		public SelectFileDialogSet (VisLabel fileLabel, Tooltip tooltip, ATSelectFileHandler handler) {
			this.fileLabel = fileLabel;
			this.tooltip = tooltip;
			this.handler = handler;
		}
	}
}

@@ -3771,25 +3771,16 @@
 tion) %7B%0A
-%09%09try %7B%0A%09
 %09%09String
@@ -3828,16 +3828,76 @@
 Class();
+%0A%09%09String handlerAlias = annotation.handlerAlias();%0A%0A%09%09try %7B
 %0A%0A%09%09%09ATS
@@ -4424,22 +4424,45 @@
 %09%09%7D%0A%0A%09%09%09
-return
+ATSelectFileHandler handler =
  group.g
@@ -4475,34 +4475,183 @@
 ias(
+h
 an
-notation.handlerAlias())
+dlerAlias);%0A%09%09%09if (handler == null) throw new IllegalStateException(%22Could not find handler for alias: %22 + handlerAlias + %22 in group: %22 + groupClassName);%0A%09%09%09return handler
 ;%0A%09%09
@@ -4792,35 +4792,17 @@
 ss: %22 + 
-annotation.handlerG
+g
 roupClas
@@ -4802,18 +4802,20 @@
 oupClass
-()
+Name
 , e);%0A%09%09

Add check if handler exists