package brn.gui.datasource;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.views.properties.IPropertySource;

import brn.gui.Activator;
import brn.gui.datasource.actions.ProviderAction;
import brn.gui.editors.DataEditor;
import brn.gui.editors.SimulatorItemInput;
import brn.gui.editors.XPlotEditor;
import brn.gui.editors.timebar.TimeBarEditor;
import brn.gui.fwdgraph.diagram.custom.editors.FwdGraphDiagramEditor;
import brn.gui.fwdgraph.diagram.custom.editors.FwdGraphDiagramEditorUtil;
import brn.gui.fwdgraph.diagram.edit.parts.GraphEditPart;
import brn.gui.linktable.diagram.custom.editors.LinkTableDiagramEditor;
import brn.gui.linktable.diagram.custom.editors.LinkTableDiagramEditorUtil;
import brn.gui.views.BeanPropertySource;
import brn.sim.AbstractParams;
import brn.sim.DriverRemote;
import brn.sim.data.PropertiesData;

public abstract class ItemImpl implements Source.Item {

  protected int id;
  protected String[] path;
  protected Source source;
  protected IPropertySource propertySource;

  protected ItemImpl(int id, String[] path, Source source) {
    this.id = id;
    this.path = path;
    this.source = source;
  }

  /**
   * @return the id
   */
  public int getId() {
    return id;
  }

  /**
   * @return the path
   */
  public String[] getPath() {
    return path;
  }

  public abstract void openInEditor(IWorkbenchWindow window);

  /*
   * (non-Javadoc)
   * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
   */
  @SuppressWarnings("unchecked")
  public Object getAdapter(Class adapter) {
    if (adapter == IPropertySource.class) {
      // TODO cache property source and offer a refresh button
//      if (propertySource == null) {
        // cache the buttonelementpropertysource
        try {
          propertySource = new BeanPropertySource(source.getContribution(this.id));
        } catch (CoreException e) {
          Activator.log(e);
          propertySource = null;
        }
//      }
      return propertySource;
    }
    return null;
  }

  public static Source.Item createItem(int id, int type, String[] path,
      Source source, ProviderAction action) {
    ItemImpl item = null;

    switch (type) {
    case DriverRemote.ITEM_TYPE_DATA:
      item = new ItemImpl.DataItemImpl(id, path, source);
      action.dataAdded(item);
      break;
    case DriverRemote.ITEM_TYPE_XPLOT:
      item = new ItemImpl.XPlotItemImpl(id, path, source);
      action.xplotAdded(item);
      break;
    case DriverRemote.ITEM_TYPE_FWDGRAPH:
      item = new ItemImpl.FwdGraphItemImpl(id, path, source);
      action.fwdGraphAdded(item);
      break;
    case DriverRemote.ITEM_TYPE_LINKTABLE:
      item = new ItemImpl.LinkTableItemImpl(id, path, source);
      action.linkTableAdded(item);
      break;
    case DriverRemote.ITEM_TYPE_ARPTABLE:
      item = new ItemImpl.ArpTableItemImpl(id, path, source);
      action.arpTableAdded(item);
      break;
    case DriverRemote.ITEM_TYPE_CONFIG:
      item = new ItemImpl.ConfigItemImpl(id, path, source);
      action.addConfig(item);
      break;
    case DriverRemote.ITEM_TYPE_PROPERTIES:
      item = new ItemImpl.PropertiesItemImpl(id, path, source);
      action.addProperties(item);
      break;
    case DriverRemote.ITEM_TYPE_TIMEBAR:
      item = new ItemImpl.TimeBarItemImpl(id, path, source);
      action.addTimeBar(item);
      break;
    default:
      break;
    }

    return item;
  }


  public static class ArpTableItemImpl extends ItemImpl implements Source.ArpTableItem {

    protected ArpTableItemImpl(int id, String[] path, Source source) {
      super(id, path, source);
    }

    @Override
    public void openInEditor(IWorkbenchWindow window) {
    }
  }

  public static class FwdGraphItemImpl extends ItemImpl implements Source.FwdGraphItem {
    protected FwdGraphItemImpl(int id, String[] path, Source source) {
      super(id, path, source);
    }

    public void openInEditor(IWorkbenchWindow window) {
      FwdGraphDiagramEditorUtil.createAndOpenDiagram(source, this.id, path,
          GraphEditPart.MODEL_ID, window, true, FwdGraphDiagramEditor.ID);
    }

  }

  public static class LinkTableItemImpl extends ItemImpl implements Source.LinkTableItem {
    protected LinkTableItemImpl(int id, String[] path, Source source) {
      super(id, path, source);
    }

    @Override
    public void openInEditor(IWorkbenchWindow window) {
      LinkTableDiagramEditorUtil.createAndOpenDiagram(source, getId(), path,
          brn.gui.linktable.diagram.edit.parts.GraphEditPart.MODEL_ID,
          window, true, LinkTableDiagramEditor.ID);
    }

  }

  public static class DataItemImpl extends ItemImpl implements Source.DataItem {
    protected DataItemImpl(int id, String[] path, Source source) {
      super(id, path, source);
    }

    @Override
    public void openInEditor(IWorkbenchWindow window) {
      try {
        window.getActivePage().openEditor(
            new SimulatorItemInput(id, source), DataEditor.ID);
      } catch (PartInitException e) {
        Activator.log(e);
      }
    }
  }

  public static class XPlotItemImpl extends ItemImpl implements Source.DataItem {
    protected XPlotItemImpl(int id, String[] path, Source source) {
      super(id, path, source);
    }

    @Override
    public void openInEditor(IWorkbenchWindow window) {
      try {
        window.getActivePage().openEditor(
            new SimulatorItemInput(id, source), XPlotEditor.ID);
      } catch (PartInitException e) {
        Activator.log(e);
      }
    }
  }

  public static class ConfigItemImpl extends ItemImpl implements Source.ConfigItem {

    protected ConfigItemImpl(int id, String[] path, Source source) {
      super(id, path, source);
    }

    @Override
    public void openInEditor(IWorkbenchWindow window) {
      try {
        window.getActivePage().showView(IPageLayout.ID_PROP_SHEET);
      } catch (PartInitException e) {
        Activator.log(e);
      }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
     */
    @SuppressWarnings("unchecked")
    public Object getAdapter(Class adapter) {
      if (adapter == IPropertySource.class) {
        AbstractParams config =  null;
        // Set config
        if (source.isConnected()) {
          try {
            config = (AbstractParams) source.getContribution(source.getConfigId());
          } catch (CoreException e) {
            Activator.log(e);
          }
        }

        if (propertySource == null) {
          // cache the propertysource
          propertySource = new BeanPropertySource(config, new String[] {
              "path", "type", "content"});
        } else {
          ((BeanPropertySource)propertySource).setBean(config);
        }
        return propertySource;
      }
      return super.getAdapter(adapter);
    }
  }

  public static class TimeBarItemImpl extends ItemImpl implements Source.TimeBarItem {

    protected TimeBarItemImpl(int id, String[] path, Source source) {
      super(id, path, source);
    }

    @Override
    public void openInEditor(IWorkbenchWindow window) {
      try {
        window.getActivePage().openEditor(
            new SimulatorItemInput(id, source), TimeBarEditor.ID);
      } catch (PartInitException e) {
        Activator.log(e);
      }
    }

    @Override
    public Object getAdapter(Class adapter) {
      if (adapter == IPropertySource.class) {
        return null;
      }
      return super.getAdapter(adapter);
    }
  }

  public static class PropertiesItemImpl extends ItemImpl implements Source.PropertiesItem {

    protected PropertiesItemImpl(int id, String[] path, Source source) {
      super(id, path, source);
    }

    @Override
    public void openInEditor(IWorkbenchWindow window) {
      try {
        window.getActivePage().showView(IPageLayout.ID_PROP_SHEET);
      } catch (PartInitException e) {
        Activator.log(e);
      }
    }

    @Override
    public Object getAdapter(Class adapter) {
      if (adapter == IPropertySource.class) {
          try {
            PropertiesData data = (PropertiesData) source.getContribution(this.id);
            propertySource = new BeanPropertySource(data.getProperties());
          } catch (CoreException e) {
            Activator.log(e);
            propertySource = null;
          }
        return propertySource;
      }
      return super.getAdapter(adapter);
    }
  }

}
