/*----------------------------------------------------------------------------
Copyright (c)2000 TogetherSoft Corporation. Patents pending. All rights reserved.
----------------------------------------------------------------------------*/
package com.togethersoft.modules.patterns.JAVA.CLASS.HP_E_Speak.Service_Provider.ui;

import com.togethersoft.modules.patterns.JAVA.CLASS.HP_E_Speak.Service_Provider.ClientProperty;
import com.togethersoft.modules.patterns.JAVA.CLASS.HP_E_Speak.Service_Provider.ClientConstant;

import  com.togethersoft.openapi.util.propertyMap.PropertyMap;
import  com.togethersoft.openapi.util.propertyMap.PropertyMapEvent;
import  com.togethersoft.openapi.util.propertyMap.PropertyMapListener;

import  com.togethersoft.openapi.sci.SciModelAccess;
import  com.togethersoft.openapi.sci.SciLanguage;
import  com.togethersoft.openapi.sci.SciInheritanceList;
import  com.togethersoft.openapi.sci.SciInheritance;
import  com.togethersoft.openapi.sci.SciClass;

import  java.util.Enumeration;

public class GeneralPage extends Page {

        private static final String SERVICE_INTERFACE_FIELD  =
        "ClassField" +
        "(" +
                "{ " +
        "title := \"Select ES Service interface\", " +
        "display_filter := if (%class%->isNode(), %class%->hasProperty(\"$interface\") && " +
                              "(%class%->hasPropertyValue(\"$extends\",\"net.espeak.jesi.ESService\") || %class%->hasPropertyValue(\"$extends\",\"ESService\")), true)" +
                " }" +
        ")";

        private static final String SERVICE_DESCRIPTION_TYPE_FIELD =
        "ChoiceField( {"+
        " values := {\"" + ClientConstant.NAME_DESCRIPTION + "\", \"" + ClientConstant.CUSTOM_DESCRIPTION + "\" },"+
        " names  := {\"   name\",\"   vocabulary\"}"+
        " } )";

        public GeneralPage(PropertyMap properties, String pagePrefix) {
                super(properties, pagePrefix);
                }

        public void init() {

                /*
                 * Create Page UI.
                 */

                setUIPropertyValue(THIS,    NULL_FIELD);
                setUIPropertyValue(VIEW_UI, TREE_TABLE_NODEUI);
                setUIPropertyValue(EXPAND_LEVEL,  ALL);

                setUIPropertyValue(ITEM + ClientProperty.SERVICE_CLASS_NAME,     STRING_FIELD);
                setUIPropertyValue(ITEM + ClientProperty.SERVICE_INTERFACE_NAME, SERVICE_INTERFACE_FIELD);
                setUIPropertyValue(ITEM + ClientProperty.ADD_SERVICE_SHORTCUT,   BOOLEAN_FIELD);

                setUIPropertyValue(ITEM + ClientProperty.SERVICE_IMPLEMENTATION, getImplementationField());

                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE, SERVICE_DESCRIPTION_TYPE_FIELD);
                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.PARAMETRIZE_NAME_CONSTRAINT,  BOOLEAN_FIELD);
                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.NAME_CONSTRAINT,              STRING_FIELD);

                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.PARAMETRIZE_XMLFILE_NAME,     BOOLEAN_FIELD);
                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.XMLFILE_NAME,                 FILENAME_FIELD);

                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.VOCABULARY_NAME,              STRING_FIELD);
                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.CUSTOM_CONSTRAINT,            STRING_FIELD);
                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.CUSTOM_CONSTRAINT + MULTIPLE, TRUE);

                /*
                 * Set up UI behaviour.
                 */

                addPropertyMapListener(ClientProperty.SERVICE_DESCRIPTION_TYPE, new PropertyMapListener() {
                        public void propertiesChanged(PropertyMapEvent propertyMapEvent) {
                                Object queryType = getProperties().getPropertyValue(ClientProperty.SERVICE_DESCRIPTION_TYPE);

                                if (ClientConstant.XML_DESCRIPTION.equals(queryType)) {
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.PARAMETRIZE_NAME_CONSTRAINT + CONDITION, FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.NAME_CONSTRAINT + CONDITION,             FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.PARAMETRIZE_XMLFILE_NAME + CONDITION,    TRUE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.XMLFILE_NAME + CONDITION,                TRUE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.CUSTOM_CONSTRAINT + CONDITION,           FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.VOCABULARY_NAME + CONDITION,             FALSE);
                                        }
                                else if (ClientConstant.CUSTOM_DESCRIPTION.equals(queryType)) {
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.PARAMETRIZE_NAME_CONSTRAINT + CONDITION, FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.NAME_CONSTRAINT + CONDITION,             FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.PARAMETRIZE_XMLFILE_NAME + CONDITION,    FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.XMLFILE_NAME + CONDITION,                FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.CUSTOM_CONSTRAINT + CONDITION,           TRUE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.VOCABULARY_NAME + CONDITION,             TRUE);
                                        }
                                else {
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.PARAMETRIZE_NAME_CONSTRAINT + CONDITION, TRUE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.NAME_CONSTRAINT + CONDITION,             TRUE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.PARAMETRIZE_XMLFILE_NAME + CONDITION,    FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.XMLFILE_NAME + CONDITION,                FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.CUSTOM_CONSTRAINT + CONDITION,           FALSE);
                                        setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.VOCABULARY_NAME + CONDITION,             FALSE);
                                        }
                                }
                        });

                addPropertyMapListener(ClientProperty.PARAMETRIZE_NAME_CONSTRAINT, new PropertyMapListener() {
                        public void propertiesChanged(PropertyMapEvent propertyMapEvent) {
                                String stringValue = FALSE;
                                Object value = getPropertyValue(ClientProperty.PARAMETRIZE_NAME_CONSTRAINT);
                                if (Boolean.FALSE.equals(value)) {
                                        stringValue = TRUE;
                                        }

                                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.NAME_CONSTRAINT + ENABLED, stringValue);

                                if (Boolean.TRUE.equals(value)) {
                                        this.previousValue = getPropertyValue(ClientProperty.NAME_CONSTRAINT);
                                        setPropertyValue(ClientProperty.NAME_CONSTRAINT, "main method parameter will be used as service name value");
                                        }
                                else {
                                        if (this.previousValue == null) {
                                                this.previousValue = getNameConstraint(getStringPropertyValue(ClientProperty.SERVICE_INTERFACE_NAME));
                                                }

                                        setPropertyValue(ClientProperty.NAME_CONSTRAINT, this.previousValue);
                                        }
                                }
                        private Object previousValue = null;
                        });

                addPropertyMapListener(ClientProperty.PARAMETRIZE_XMLFILE_NAME, new PropertyMapListener() {
                        public void propertiesChanged(PropertyMapEvent propertyMapEvent) {
                                String stringValue = FALSE;
                                Object value = getPropertyValue(ClientProperty.PARAMETRIZE_XMLFILE_NAME);
                                if (Boolean.FALSE.equals(value)) {
                                        stringValue = TRUE;
                                        }

                                setUIPropertyValue(ITEM + ClientProperty.SERVICE_DESCRIPTION_TYPE + ITEM + ClientProperty.XMLFILE_NAME + ENABLED, stringValue);

                                if (Boolean.TRUE.equals(value)) {
                                        this.previousValue = getPropertyValue(ClientProperty.XMLFILE_NAME);
                                        setPropertyValue(ClientProperty.XMLFILE_NAME, "main method parameter will be used as service name value");
                                        }
                                else {
                                        setPropertyValue(ClientProperty.XMLFILE_NAME, this.previousValue);
                                        }
                                }
                        private Object previousValue = "";
                        });

                addPropertyMapListener(ClientProperty.SERVICE_INTERFACE_NAME, new PropertyMapListener() {
                        public void propertiesChanged(PropertyMapEvent propertyMapEvent) {
                                String serviceName = getStringPropertyValue(ClientProperty.SERVICE_INTERFACE_NAME);
                                if ((serviceName == null) || (serviceName.trim().length() <= 0)) {
                                        return;
                                        }

                                setUIPropertyValue(ITEM + ClientProperty.SERVICE_IMPLEMENTATION, getImplementationField());
                                setPropertyValue(ClientProperty.SERVICE_IMPLEMENTATION, findImplementation(serviceName));
                                setPropertyValue(ClientProperty.SERVICE_CLASS_NAME, getProviderName(serviceName));
                                setPropertyValue(ClientProperty.VOCABULARY_NAME, getNameConstraint(serviceName) + "Vocabulary");

                                SciClass ifaceClazz = SciModelAccess.getModel().findClass(SciLanguage.JAVA, serviceName);
                                if (ifaceClazz == null) {
                                        return;
                                        }

                                String enableShortcut = TRUE;
                                if (ifaceClazz.getContainingPackage().equals(getContainingPackage())) {
                                        enableShortcut = FALSE;
                                        setPropertyValue(ClientProperty.ADD_SERVICE_SHORTCUT, Boolean.FALSE);
                                        }

                                setUIPropertyValue(ITEM + ClientProperty.ADD_SERVICE_SHORTCUT + ENABLED, enableShortcut);

                                if (getPropertyValue(ClientProperty.PARAMETRIZE_NAME_CONSTRAINT).equals(Boolean.FALSE)) {
                                        setPropertyValue(ClientProperty.NAME_CONSTRAINT, getNameConstraint(serviceName));
                                        }

                                if (getPropertyValue(ClientProperty.PARAMETRIZE_XMLFILE_NAME).equals(Boolean.FALSE)) {
                                        setPropertyValue(ClientProperty.XMLFILE_NAME, getNameConstraint(serviceName) + ".xml");
                                        }
                                }
                        });

                /*
                 * Set initial values.
                 */
                setPropertyValue(ClientProperty.SERVICE_DESCRIPTION_TYPE, ClientConstant.NAME_DESCRIPTION);
                setPropertyValue(ClientProperty.PARAMETRIZE_NAME_CONSTRAINT, Boolean.FALSE);
                setPropertyValue(ClientProperty.PARAMETRIZE_XMLFILE_NAME,    Boolean.FALSE);
                setPropertyValue(ClientProperty.ADD_SERVICE_SHORTCUT, Boolean.FALSE);

                addPropertyValue(ClientProperty.CUSTOM_CONSTRAINT, "Name");
                }

        private String getProviderName(String serviceName) {

                for(int i = 1; i > 0; i++) {
                        String name = getNameConstraint(serviceName) + "ServiceProvider" + i;
                        String qualifiedName = getContainingPackage().getQualifiedName() + '.' + name;
                        if (qualifiedName.startsWith(".")) {
                                qualifiedName = qualifiedName.substring(".".length());
                                }

                        if (SciModelAccess.getModel().findClass(SciLanguage.JAVA, qualifiedName) == null) {
                                return name;
                                }
                        }

                return null;
                }

        private static String getNameConstraint(String serviceName) {
                if (serviceName == null) {
                        return "";
                        }

                String shortName = serviceName;
                int dot = shortName.lastIndexOf('.');
                if (dot >= 0) {
                        shortName = shortName.substring(dot + 1);
                        }

                if (shortName.toLowerCase().endsWith("intf")) {
                        shortName = shortName.substring(0, shortName.length() - "intf".length());
                        }
                else if (shortName.toLowerCase().endsWith("interface")) {
                        shortName = shortName.substring(0, shortName.length() - "interface".length());
                        }

                return shortName;
                }

        private String findImplementation(String qualifiedName) {
                SciClass serviceClazz = SciModelAccess.getModel().findClass(SciLanguage.JAVA, qualifiedName);
                if (serviceClazz == null) {
                        return null;
                        }

                for(Enumeration classes = getContainingPackage().classes(); classes.hasMoreElements();) {
                        SciClass clazz = (SciClass) classes.nextElement();
                        System.out.println("checking " + clazz.getQualifiedName());

                        SciInheritanceList inheritanceList = clazz.getImplementsList();
                        if (inheritanceList == null) {
                                continue;
                                }

                        for (Enumeration inheritances = inheritanceList.inheritances(); inheritances.hasMoreElements();) {
                                SciInheritance inheritor = (SciInheritance) inheritances.nextElement();

                                if (serviceClazz.equals(inheritor.getReferencedElement())) {
                                        return clazz.getQualifiedName();
                                        }
                                }
                        }
                return null;
                }

        private String getImplementationField() {
                return "ClassField" +
                                "(" +
                                        "{ " +
                                                "title := \"Select Service implementation (" + getStringPropertyValue(ClientProperty.SERVICE_INTERFACE_NAME) + ")\", " +
                                                "display_filter := if (%class%->isNode(), !%class%->hasProperty(\"$interface\") && " +
                                                "(%class%->hasPropertyValue(\"$implements\",\"" + getStringPropertyValue(ClientProperty.SERVICE_INTERFACE_NAME) + "\")), true)" +
                                        " }" +
                                 ")";
                }
        }


