/*-------------------------------------------------------------------------------
Copyright (c)2000 TogetherSoft Corporation. Patents pending. All rights reserved.
-------------------------------------------------------------------------------*/

package com.togethersoft.modules.patterns.JAVA.CLASS.Bean;

import java.util.Enumeration;
import java.util.Vector;

import com.togethersoft.openapi.sci.*;
import com.togethersoft.openapi.sci.pattern.SciPattern;
import com.togethersoft.openapi.sci.pattern.SciPatternProperty;
import com.togethersoft.openapi.sci.pattern.SciPatternUtil;

import com.togethersoft.openapi.ide.message.IdeMessageManagerAccess;
import com.togethersoft.openapi.ide.message.IdeMessageType;

import com.togethersoft.openapi.util.propertyMap.Property;

import com.togethersoft.modules.patterns.UNIVERSAL.PatternBase;
import com.togethersoft.modules.patterns.UNIVERSAL.PatternBaseException;
import com.togethersoft.modules.patterns.UNIVERSAL.PatternUIBuilder;

/**
 * @version 3.0.0
 * @author TogetherSoft
 */
public class Pattern extends PatternBase implements SciPattern {

    private static final String PATTERN_NAME = "Bean";

    public Pattern() {
        setPatternDisplayName(PATTERN_NAME);

        // Initialize PropertyMap
        setPropertyValue(NAME, BEAN);
        addPropertyValue(PROPERTY, PROPERTY.toLowerCase());
        setPropertyValue(GENERATE_GET_METHODS, Boolean.TRUE);
        setPropertyValue(GENERATE_SET_METHODS, Boolean.TRUE);
        setPropertyValue(CREATE_DEFAULT_CTOR, Boolean.TRUE);
        setPropertyValue(SET_VISIBILITY, myVisibilityItems[0]);
    }

    protected void finalize() throws Throwable {
        super.finalize();
        if (myUIBuilder != null) {
            myUIBuilder.removeAllListenedInspectorProperties();
            myUIBuilder = null;
        }

        aClass = null;
        myVisibilityItems = null;
    }

    public boolean prepare() {
        super.prepare();

        try {
            setPropertyValue(PROPERTY, null);

            SciElement element = getElement();
            if (element == null) {
                aClass = null;
                setPropertyValue(NAME, BEAN);
            }
            else {
                if (!(element instanceof SciClass)) {
                    throw new PatternBaseException("This pattern could be applied to the class only");
                }
                aClass = (SciClass)element;
                cannotApplyToInterface(aClass);
                setPropertyValue(NAME, aClass.getName());
            }

            if (!propertiesEnumeration(PROPERTY).hasMoreElements()) {
                addPropertyValue(PROPERTY, PROPERTY.toLowerCase());
            }

            initializeInspector();
            assignActivityResponse();
            return true;
        }
        catch(PatternBaseException e) {
            return false;
        }
    }

    public boolean canApply() {
        try {
            classNameShouldBeCorrect(NAME);

            Enumeration properties = propertiesEnumeration(PROPERTY);
            if (!properties.hasMoreElements()) {
                // prevent finishing without properties
                throw new PatternBaseException("At least one property should be defined.");
            }

            Property property = null;
            while (properties.hasMoreElements()) {
                property = (Property) properties.nextElement();
                checkStringValue((String)property.getValue(), false);
            }

            return true;
        }
        catch(PatternBaseException e) {
            return false;
        }
    }

    public void apply() {
        if (!canApply()) {
            return;
        }
        super.apply();

        String beanName = getStringPropertyValue(NAME);
        if (aClass == null) {
            aClass = getClassByName(beanName, false);
        }
        else {
            aClass.setName(beanName);
        }

        String visibility = getStringPropertyValue(SET_VISIBILITY);
        boolean createGetMethods = getBooleanPropertyValue(GENERATE_GET_METHODS);
        boolean createSetMethods = getBooleanPropertyValue(GENERATE_SET_METHODS);
        boolean createDefConstructor = getBooleanPropertyValue(CREATE_DEFAULT_CTOR);

        Enumeration properties = propertiesEnumeration(PROPERTY);
        while (properties.hasMoreElements()) {
            Property    property = (Property) properties.nextElement();
            String      propertyMemberString = (String)property.getValue();
            SciMember   propertyMember = null;

            if (getLanguageHelper().isValidIdentifier(propertyMemberString)) {
                propertyMember = getFactory().newAttribute();
                propertyMember.setName(propertyMemberString);
            }
            else {
                try {
                    propertyMember = getGenericFactory().newMember(propertyMemberString + ";", aClass);
                }
                catch(SciGenericFactoryException e) {
                    continue;
                }
            }

            if (!(propertyMember instanceof SciAttribute))
                continue;

            if (SciUtil.findMemberBySignature(aClass, propertyMember) != null)
                continue;

            propertyMember = (SciMember)aClass.paste(propertyMember, null, false);
            if (PRIVATE.equals(visibility)) {
                propertyMember.setProperty(SciProperty.PRIVATE, true);
            }
            else if (PROTECTED.equals(visibility)) {
                propertyMember.setProperty(SciProperty.PROTECTED, true);
            }
            else if (PACK_LOCAL.equals(visibility)) {
                propertyMember.setProperty(SciProperty.PACKAGE_LOCAL, true);
            }
            else if (PUBLIC.equals(visibility)) {
                propertyMember.setProperty(SciProperty.PUBLIC, true);
            }

            SciPatternUtil.addAttributeToConstructors((SciAttribute)propertyMember);

            if (createGetMethods)
                SciPatternUtil.createGetMethod((SciAttribute)propertyMember);

            if (createSetMethods)
                SciPatternUtil.createSetMethod((SciAttribute)propertyMember);

            if (createDefConstructor) {
                SciOperation defaultCtor = getFactory().newOperation();
                defaultCtor.setProperty(SciProperty.CONSTRUCTOR, true);
                aClass.paste(defaultCtor, null, false);
            }
        } // while (properties...

        setPropertyValue(SciPatternProperty.RESULT_ELEMENT, aClass);
    }

    protected void initializeInspector() {
        try {
            myUIBuilder = null;
            myUIBuilder = createUIBuilder(true);

            Vector inspectorPropertiesVector = new Vector();

            // Create page
            String pageName1 = "Pattern properties";
            if (myUIBuilder.addInspectorPage(pageName1, PatternUIBuilder.UIPresentation.Table) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }

            // Add NAME property
            if (myUIBuilder.addPropertyToPage(pageName1, NAME, NAME,
                PatternUIBuilder.PropertyType.String) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(NAME);

            // Add PROPERTY property
            if (myUIBuilder.addPropertyToPage(pageName1, PROPERTY, PROPERTY,
                PatternUIBuilder.PropertyType.MultiString) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(PROPERTY);

            // Add GENERATE_GET_METHODS property
            if (myUIBuilder.addPropertyToPage(pageName1, GENERATE_GET_METHODS, GENERATE_GET_METHODS,
                PatternUIBuilder.PropertyType.Boolean) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(GENERATE_GET_METHODS);

            // Add GENERATE_SET_METHODS property
            if (myUIBuilder.addPropertyToPage(pageName1, GENERATE_SET_METHODS, GENERATE_SET_METHODS,
                PatternUIBuilder.PropertyType.Boolean) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(GENERATE_GET_METHODS);

            // Add CREATE_DEFAULT_CTOR property
            if (myUIBuilder.addPropertyToPage(pageName1, CREATE_DEFAULT_CTOR, CREATE_DEFAULT_CTOR,
                PatternUIBuilder.PropertyType.Boolean) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(CREATE_DEFAULT_CTOR);

            // Add SET_VISIBILITY property
            if (myUIBuilder.addPropertyToPage(pageName1, SET_VISIBILITY, SET_VISIBILITY,
                PatternUIBuilder.PropertyType.StringChooser, myVisibilityItems) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(SET_VISIBILITY);

            myUIBuilder.setCreatedPatternUI();
            myUIBuilder.assignListenedInspectorProperties(inspectorPropertiesVector);
        }
        catch (PatternBaseException ex) {
            myUIBuilder = null;
            getIdeInspector().clear();
            return;
        }
    }

    protected void assignActivityResponse() {
    }

    private PatternUIBuilder myUIBuilder = null;

    private SciClass aClass = null;

    private static final String BEAN        = "Bean";
    private static final String PROPERTY    = "Property";
    private static final String NAME        = "Name";

    private static String[] myVisibilityItems = new String[] { PRIVATE, PROTECTED, PACK_LOCAL, PUBLIC };

    private static final String GENERATE_GET_METHODS    = "Generate get methods";
    private static final String GENERATE_SET_METHODS    = "Generate set methods";
    private static final String SET_VISIBILITY          = "Set visibility";
    private static final String CREATE_DEFAULT_CTOR     = "Create default constructor";
}
