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

package com.togethersoft.modules.inspector;

import com.togethersoft.openapi.ide.IdeStartup;
import com.togethersoft.openapi.ide.IdeContext;
import com.togethersoft.openapi.ide.inspector.*;
import com.togethersoft.openapi.ide.inspector.util.*;
import com.togethersoft.openapi.ide.inspector.util.property.*;
import com.togethersoft.openapi.ide.inspector.util.table.*;
import com.togethersoft.openapi.ide.inspector.util.editors.*;
import com.togethersoft.openapi.ide.util.*;
import com.togethersoft.openapi.rwi.*;

import javax.swing.DefaultComboBoxModel;
import com.togethersoft.openapi.util.RwiElementsUtil;

/**
 * @author TogetherSoft
 */
public class AssociatesLinkInspector implements IdeStartup, IdeInspectorBuilder {
  public void autorun(){
    IdeInspectorManager manager = IdeInspectorManagerAccess.getInspectorManager();
    manager.addInspectorBuilder(this);
  }
  public IdeInspector buildInspector(IdeContext context, IdeInspector inspector) {
    if (!RwiElementsUtil.checkProperty(context, RwiProperty.SHAPE_TYPE, RwiShapeType.ASSOCIATES_LINK))
      return inspector;
    RwiElement[] rwiElements = RwiElementsUtil.getRwiElements(context);
    RwiReference[] rwiReferences = RwiElementsUtil.getRwiReferences(context);

    IdeInspectorComponent propertiesComponent = inspector.findComponent("Link");
    IdeInspectorPropertySetComponent propertiesPage;
    if (propertiesComponent instanceof IdeInspectorPropertySetComponent) {
      propertiesPage = (IdeInspectorPropertySetComponent)propertiesComponent;
    }
    else {
      propertiesPage = new IdeInspectorPropertySetComponent(context);
      propertiesPage.setName("Link");
      propertiesPage.setService(UIComponentService.class, new PropertyTableComponentUI(propertiesPage));
      inspector.addComponent(propertiesPage, null, ComponentWeight.PROPERTIES);
    }

    IdeInspectorProperty property;

    if (rwiElements.length == 1 && rwiElements[0] instanceof RwiLink) {
      String sourceName = ((RwiLink)rwiElements[0]).getSource().getProperty(RwiProperty.NAME);
      property = new ReadOnlyProperty(sourceName, String.class);
      property.setName("client");
      propertiesPage.addProperty(property, null);

      String destinationName = ((RwiLink)rwiElements[0]).getDestination().getProperty(RwiProperty.NAME);
      property = new ReadOnlyProperty(destinationName, String.class);
      property.setName("supplier");
      propertiesPage.addProperty(property, null);
    }

    property = new RwiInspectorStringProperty(rwiElements, "label");
    property.setName("label");
    propertiesPage.addProperty(property, null);

    property = new RwiInspectorStringProperty(rwiElements, "clientRole");
    property.setName("client role");
    propertiesPage.addProperty(property, null);

    boolean haveCardinalities = true;
    for (int i = 0; i < rwiElements.length; i++) {
      if (RwiShapeType.OBJECT.equals(((RwiLink)rwiElements[i]).getDestination().getProperty(RwiProperty.SHAPE_TYPE))) {
        haveCardinalities = false;
      }
    }
    if (haveCardinalities){
      property = new RwiInspectorStringProperty(rwiElements, "clientCardinality");
      SwingComboBoxEditor editor = new SwingComboBoxEditor(
        new DefaultComboBoxModel(
          new String[] {
            "0..1", "1", "*", "1..*"
          }
        )
      );
      editor.setValueEditable(true);
      property.setPropertyEditor(editor);
      property.setName("client cardinality");
      propertiesPage.addProperty(property, null);
    }

    property = new RwiInspectorStringProperty(rwiElements, "supplierRole");
    property.setName("supplier role");
    propertiesPage.addProperty(property, null);

    if (haveCardinalities){
      property = new RwiInspectorStringProperty(rwiElements, "supplierCardinality");
      SwingComboBoxEditor editor = new SwingComboBoxEditor(
        new DefaultComboBoxModel(
          new String[] {
            "0..1", "1", "*", "1..*"
          }
        )
      );
      editor.setValueEditable(true);
      property.setPropertyEditor(editor);
      property.setName("supplier cardinality");
      propertiesPage.addProperty(property, null);
    }

    property = new RwiInspectorBooleanProperty(rwiElements, "directed");
    property.setName("directed");
    propertiesPage.addProperty(property, null);

    property = new RwiInspectorAssociatesProperty(rwiElements);
    SwingComboBoxEditor editor = new SwingComboBoxEditor(
      new DefaultComboBoxModel(
        new String[] {
          RwiInspectorAssociatesProperty.ASSOCIATION, RwiInspectorAssociatesProperty.AGGREGATION, RwiInspectorAssociatesProperty.COMPOSITION
        }
      ), null, null
    );
    editor.setValueEditable(false);
    property.setPropertyEditor(editor);
    property.setName("type");
    propertiesPage.addProperty(property, null);

    if (rwiElements.length == 1) {
      InspectorUtils.createDescriptionPage (context, inspector, rwiElements);
      inspector.addComponent(new DocComponent(rwiElements[0]), null, ComponentWeight.HTMLDOC);
      InspectorUtils.createReqPage (context, inspector, rwiElements);
    }

    return inspector;
  }
}

class RwiInspectorAssociatesProperty extends RwiInspectorProperty {
  public RwiInspectorAssociatesProperty(RwiPropertyMap[] rwiPropertyMaps) {
    super(rwiPropertyMaps, "", String.class);
  }

  public RwiInspectorAssociatesProperty(RwiPropertyMap rwiPropertyMap) {
    super(new RwiPropertyMap[] { rwiPropertyMap }, "", String.class);
  }

  protected void loadValue() {
    myReadableFlag = true;
    myWritableFlag = true;
    Object value = ASSOCIATION;
    for (int i = 0; i < myRwiPropertyMaps.length; i++) {
      if (isDeleted(myRwiPropertyMaps[i]) || !RwiShapeType.ASSOCIATES_LINK.equals(myRwiPropertyMaps[i].getProperty(RwiProperty.SHAPE_TYPE)) ) {
        value = UNDEFINED_VALUE;
        myReadableFlag = false;
        myWritableFlag = false;
        break;
      }

      String val = ASSOCIATION;
      if (myRwiPropertyMaps[i].hasProperty("composition"))
        val = COMPOSITION;
      else if (myRwiPropertyMaps[i].hasProperty("aggregation"))
        val = AGGREGATION;
      if (i == 0) {
        value = val;
      } else {
        if (val != value) {
          value = val;
          break;
        }
      }
    }
    Object oldValue = myValue;
    myValue = value;
    firePropertyChange(PROP_VALUE, oldValue, myValue);
  }

  protected void storeValue() {
    for (int i = 0; i < myRwiPropertyMaps.length; i++) {
      if (isDeleted(myRwiPropertyMaps[i])) { continue; }
      if ( COMPOSITION.equals(myValue) ) {
        myRwiPropertyMaps[i].setProperty("composition", true);
        myRwiPropertyMaps[i].setProperty("aggregation", true);
      } else if ( AGGREGATION.equals(myValue) ) {
        myRwiPropertyMaps[i].setProperty("composition", false);
        myRwiPropertyMaps[i].setProperty("aggregation", true);
      } else {
        myRwiPropertyMaps[i].setProperty("composition", false);
        myRwiPropertyMaps[i].setProperty("aggregation", false);
      }
    }
  }

  public boolean canSetValue(Object value) {
    return true;
  }

  public static final String ASSOCIATION = "Association";
  public static final String COMPOSITION = "Composition";
  public static final String AGGREGATION = "Aggregation";
}

