package org.orienteer.pivottable.component;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.html.panel.GenericPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.util.template.PackageTextTemplate;
import org.apache.wicket.util.template.TextTemplate;
import org.orienteer.core.component.property.DisplayMode;
import org.orienteer.core.widget.support.jquery.JQueryDashboardSupport;

import de.agilecoders.wicket.webjars.request.resource.WebjarsCssResourceReference;
import de.agilecoders.wicket.webjars.request.resource.WebjarsJavaScriptResourceReference;

/**
 * Panel to show pivot
 */
public class PivotPanel extends GenericPanel<String> {
	
	private static final WebjarsCssResourceReference PIVOT_CSS = new WebjarsCssResourceReference("/webjars/pivottable/current/dist/pivot.min.css");
	private static final WebjarsJavaScriptResourceReference PIVOT_JS = new WebjarsJavaScriptResourceReference("/webjars/pivottable/current/dist/pivot.min.js");
	private static final CssResourceReference PIVOT_CSS_FIX = new CssResourceReference(PivotPanel.class, "pivottable.css");

	
	private static final WebjarsJavaScriptResourceReference D3_JS = new WebjarsJavaScriptResourceReference("/webjars/d3/current/d3.min.js");
	private static final WebjarsJavaScriptResourceReference D3_RENDERERS_JS = new WebjarsJavaScriptResourceReference("/webjars/pivottable/current/dist/d3_renderers.min.js");
	
	private static final WebjarsCssResourceReference C3_CSS = new WebjarsCssResourceReference("/webjars/c3/current/c3.min.css");
	private static final WebjarsJavaScriptResourceReference C3_JS = new WebjarsJavaScriptResourceReference("/webjars/c3/current/c3.min.js");
	private static final WebjarsJavaScriptResourceReference C3_RENDERERS_JS = new WebjarsJavaScriptResourceReference("/webjars/pivottable/current/dist/c3_renderers.min.js");
	
	private static final List<String> SUPPORTED_LANGS = Arrays.asList("en", "es", "fr", "nl", "pt", "ru", "tr", "zh");
	private static final Map<String, WebjarsJavaScriptResourceReference> LANGUAGES_MAP = new HashMap<>();
	
	private final IModel<String> configModel;
	private final IModel<DisplayMode> modeModel;
	private final UpdatePivotTableBehavior updatePivotTableBehavior;
	
	private class UpdatePivotTableBehavior extends AbstractDefaultAjaxBehavior {

		@Override
		protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
			super.updateAjaxAttributes(attributes);
			attributes.getDynamicExtraParameters().add("return {config: JSON.stringify(cfg)};");
			attributes.setMethod(Method.POST);
		}
		
		@Override
		protected void respond(AjaxRequestTarget target) {
			if(configModel!=null) 
				configModel.setObject(RequestCycle.get().getRequest().getRequestParameters()
					 .getParameterValue("config").toString());
		}
		
		@Override
		public boolean isEnabled(Component component) {
			DisplayMode mode = modeModel!=null?modeModel.getObject():DisplayMode.VIEW;
			return DisplayMode.EDIT.equals(mode);
		}
		
	}
	
	public PivotPanel(String id, IModel<String> urlModel, IModel<DisplayMode> modeModel, IModel<String> configModel) {
		super(id, urlModel);
		setOutputMarkupId(true);
		this.modeModel = modeModel;
		this.configModel = configModel;
		add(updatePivotTableBehavior = new UpdatePivotTableBehavior());
	}
	
	@Override
	public void detachModels() {
		super.detachModels();
		modeModel.detach();
		configModel.detach();
	}
	
	protected JavaScriptResourceReference getLocalizationJSResource(String lang) {
		if(Strings.isEmpty(lang) || "en".equals(lang)) return null;
		WebjarsJavaScriptResourceReference ret = LANGUAGES_MAP.get(lang);
		if(ret==null) {
			ret = new WebjarsJavaScriptResourceReference("/webjars/pivottable/current/dist/pivot."+lang+".min.js");
			LANGUAGES_MAP.put(lang, ret);
		}
		return ret;
	}
	
	@Override
	public void renderHead(IHeaderResponse response) {
		super.renderHead(response);
		response.render(CssHeaderItem.forReference(PIVOT_CSS));
		response.render(CssHeaderItem.forReference(PIVOT_CSS_FIX));
		response.render(CssHeaderItem.forReference(C3_CSS));
		response.render(JavaScriptHeaderItem.forReference(JQueryDashboardSupport.JQUERY_UI_JS));
		response.render(JavaScriptHeaderItem.forReference(PIVOT_JS));
		response.render(JavaScriptHeaderItem.forReference(D3_JS));
		response.render(JavaScriptHeaderItem.forReference(C3_JS));
		response.render(JavaScriptHeaderItem.forReference(D3_RENDERERS_JS));
		response.render(JavaScriptHeaderItem.forReference(C3_RENDERERS_JS));
		String lang = getLocale().getLanguage();
		if(SUPPORTED_LANGS.indexOf(lang)<0) lang = "en";
		JavaScriptResourceReference langRes = getLocalizationJSResource(lang);
		if(langRes!=null) response.render(JavaScriptHeaderItem.forReference(langRes));
		TextTemplate template = new PackageTextTemplate(PivotPanel.class, "pivottable.tmpl.js");
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("componentId", getMarkupId());
		params.put("dataUrl", getModelObject().replace("'", "\\'"));
		params.put("config", Strings.defaultIfEmpty(configModel.getObject(), "{}"));
		params.put("editMode", DisplayMode.EDIT.equals(modeModel.getObject()));
		params.put("callBackScript", updatePivotTableBehavior.getCallbackScript());
		params.put("language", lang);
		template.interpolate(params);
		response.render(OnDomReadyHeaderItem.forScript(template.asString()));
	}
	
}
