/*
 * Copyright 2002-2005 Sascha Weinreuter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.intellij.plugins.xpathView.ui;

import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.ide.DataManager;
import com.intellij.javaee.ExternalResourceManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.DimensionService;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlElement;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.AnActionButtonRunnable;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.util.containers.BidirectionalMap;
import com.intellij.util.ui.PlatformColors;
import com.intellij.util.ui.Table;
import com.intellij.util.ui.UIUtil;
import org.intellij.lang.xpath.XPathFileType;
import org.intellij.lang.xpath.context.*;
import org.intellij.lang.xpath.psi.XPathElement;
import org.intellij.plugins.xpathView.util.MyPsiUtil;
import org.intellij.plugins.xpathView.util.Namespace;
import org.intellij.plugins.xpathView.util.Variable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.xml.namespace.QName;
import java.awt.*;
import java.util.*;
import java.util.List;

import static org.intellij.plugins.xpathView.util.Copyable.Util.copy;

public class EditContextDialog extends DialogWrapper {
  private final DimensionService myDimensionService = DimensionService.getInstance();

  private final Set<String> myUnresolvedPrefixes;

  private final JTable myVariableTable;
  private final VariableTableModel myVariableTableModel;

  private final JTable myNamespaceTable;
  private final NamespaceTableModel myNamespaceTableModel;
  private final ContextProvider myContextProvider;
  private Splitter mySplitter;

  public EditContextDialog(Project project,
                           Set<String> unresolvedPrefixes,
                           Collection<Namespace> namespaces,
                           Collection<Variable> variables,
                           ContextProvider contextProvider) {
    super(project, false);
    myUnresolvedPrefixes = unresolvedPrefixes;

    setTitle("Edit XPath Context");
    setModal(true);

    myContextProvider = new MyContextProvider(contextProvider);

    final List<Variable> m = copy(variables);
    myVariableTableModel = new VariableTableModel(m, project, XPathFileType.XPATH);
    myVariableTable = new Table(myVariableTableModel);
    myVariableTable.setDefaultRenderer(String.class, new VariableCellRenderer(m));
    myVariableTable.setDefaultRenderer(Expression.class, new ExpressionCellRenderer(project));
    myVariableTable.setDefaultEditor(Expression.class, new ExpressionCellEditor(project));

    int width = new JLabel("Name").getPreferredSize().width;
    myVariableTable.getColumnModel().getColumn(0).setMinWidth(width);
    myVariableTable.getColumnModel().getColumn(0).setMaxWidth(width * 5);
    myVariableTable.setPreferredScrollableViewportSize(new Dimension(200, 130));

    final List<Namespace> n = copy(namespaces);
    myNamespaceTableModel = new NamespaceTableModel(n);
    myNamespaceTable = new Table(myNamespaceTableModel);
    myNamespaceTable.setDefaultRenderer(String.class, new NamespaceCellRenderer(n));

    width = new JLabel("Prefix").getPreferredSize().width;
    myNamespaceTable.getColumnModel().getColumn(0).setMinWidth(width);
    myNamespaceTable.getColumnModel().getColumn(0).setMaxWidth(width * 4);
    myNamespaceTable.setPreferredScrollableViewportSize(new Dimension(200, 150));

    init();
  }

  protected JComponent createCenterPanel() {
    final JPanel p = ToolbarDecorator.createDecorator(myVariableTable)
      .setAddAction(new AnActionButtonRunnable() {
        @Override
        public void run(AnActionButton button) {
          stopVarEditing();
          myVariableTableModel.addVariable();
          myNamespaceTable.editCellAt(myVariableTableModel.getRowCount() - 1, 0);
        }
      }).setRemoveAction(new AnActionButtonRunnable() {
        @Override
        public void run(AnActionButton button) {
          myVariableTableModel.removeVariable(myVariableTable.getSelectedRow());
        }
      }).disableUpDownActions().createPanel();
    UIUtil.addBorder(p, IdeBorderFactory.createTitledBorder("Variables", false));

    final JPanel n = ToolbarDecorator.createDecorator(myNamespaceTable)
      .setAddAction(myContextProvider.getContextElement() != null ? null : new AnActionButtonRunnable() {
        @Override
        public void run(AnActionButton button) {
          final ExternalResourceManager erm = ExternalResourceManager.getInstance();
          final List<String> allURIs = new ArrayList<String>(Arrays.asList(erm.getResourceUrls(null, true)));
          final Collection<Namespace> namespaces = myNamespaceTableModel.getNamespaces();
          for (Namespace namespace : namespaces) {
            allURIs.remove(namespace.getUri());
          }
          Collections.sort(allURIs);

          final DataContext dataContext = DataManager.getInstance().getDataContext(myNamespaceTable);
          final Project project = CommonDataKeys.PROJECT.getData(dataContext);
          final AddNamespaceDialog dlg = new AddNamespaceDialog(project, myUnresolvedPrefixes, allURIs, AddNamespaceDialog.Mode.EDITABLE);
          dlg.show();
          if (dlg.isOK()) {
            myNamespaceTableModel.addNamespace(new Namespace(dlg.getPrefix(), dlg.getURI()));
          }
        }
      }).setRemoveAction(
        myContextProvider.getContextElement() != null ? null : new AnActionButtonRunnable() {
          @Override
          public void run(AnActionButton button) {
            myNamespaceTableModel.removeNamespace(myNamespaceTable.getSelectedRow());
          }
        }).disableUpDownActions().createPanel();
    UIUtil.addBorder(n, IdeBorderFactory.createTitledBorder("Namespaces", false));

    int extendedState = myDimensionService.getExtendedState(getDimensionServiceKey());
    if (extendedState == -1) extendedState = 400;
    mySplitter = new Splitter(true, extendedState / 1000f);
    mySplitter.setHonorComponentsMinimumSize(true);
    mySplitter.setFirstComponent(n);
    mySplitter.setSecondComponent(p);

    return mySplitter;
  }


  protected String getDimensionServiceKey() {
    return getClass().getName() + ".DIMENSION_SERVICE_KEY";
  }

  public Pair<Collection<Namespace>, Collection<Variable>> getContext() {
    assert isOK();

    return Pair.create(myNamespaceTableModel.getNamespaces(), myVariableTableModel.getVariables());
  }

  protected void doOKAction() {
    stopVarEditing();
    stopNamespaceEditing();

    final List<Expression> expressions = myVariableTableModel.getExpressions();
    for (int i = 0; i < expressions.size(); i++) {
      final Expression expression = expressions.get(i);
      final String name = (String)myVariableTableModel.getValueAt(i, 0);

      final String expr = expression.getExpression();
      if ((expr == null || expr.trim().length() == 0) && (name == null || name.trim().length() == 0)) {
        continue;
      }
      final String error = getError(expression);
      if (error != null) {
        Messages.showErrorDialog(expression.getFile().getProject(), "Error in XPath Expression for Variable '" + name + "': " + error,
                                 "XPath Error");
        myVariableTable.getSelectionModel().setSelectionInterval(i, i);
        return;
      }
    }
    super.doOKAction();
  }

  public void show() {
    super.show();
    if (mySplitter != null) {
      myDimensionService.setExtendedState(getDimensionServiceKey(), (int)(mySplitter.getProportion() * 1000));
    }
  }

  private String getError(final Expression expression) {
    return MyPsiUtil.checkFile(expression.getFile());
  }

  private void stopVarEditing() {
    final TableCellEditor cellEditor = myVariableTable.getCellEditor();
    if (cellEditor != null) {
      cellEditor.stopCellEditing();
    }
  }

  private void stopNamespaceEditing() {
    final TableCellEditor cellEditor = myNamespaceTable.getCellEditor();
    if (cellEditor != null) {
      cellEditor.stopCellEditing();
    }
  }

  private class VariableTableModel extends AbstractTableModel {
    private final Project myProject;
    private final LanguageFileType myFileType;

    private final List<Variable> myVariables;
    private final List<Expression> myList;

    public VariableTableModel(List<Variable> variables, Project project, LanguageFileType fileType) {
      this.myVariables = variables;
      this.myProject = project;
      this.myFileType = fileType;

      myList = new ArrayList<Expression>(variables.size());
      for (Variable variable : variables) {
        final Expression expression = Expression.create(project, fileType, variable.getExpression());
        myContextProvider.attachTo(expression.getFile());
        myList.add(expression);
      }
    }

    public Class<?> getColumnClass(int columnIndex) {
      return columnIndex == 0 ? String.class : Expression.class;
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return true;
    }

    public String getColumnName(int column) {
      return column == 0 ? "Name" : "Expression";
    }

    public int getRowCount() {
      return myVariables.size();
    }

    public int getColumnCount() {
      return 2;
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
      final Variable variable = myVariables.get(rowIndex);
      if (columnIndex == 0) {
        return variable.getName();
      }
      else {
        return myList.get(rowIndex);
      }
    }

    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
      if (rowIndex >= myVariables.size()) {
        return;
      }
      final Variable variable = myVariables.get(rowIndex);
      if (columnIndex == 0) {
        variable.setName((String)aValue);
      }
      else {
        variable.setExpression(((Expression)aValue).getExpression());
      }
      fireTableDataChanged();
    }

    public Collection<Variable> getVariables() {
      return myVariables;
    }

    public List<Expression> getExpressions() {
      return myList;
    }

    public void addVariable() {
      final Variable variable = new Variable();
      myVariables.add(variable);
      final Expression expression = Expression.create(myProject, myFileType);
      myContextProvider.attachTo(expression.getFile());
      myList.add(expression);

      final int firstRow = myVariables.size() - 1;
      fireTableRowsInserted(firstRow, firstRow);
    }

    public void removeVariable(int selectedRow) {
      myVariables.remove(selectedRow);
      myList.remove(selectedRow);
      fireTableRowsDeleted(selectedRow, selectedRow);
    }
  }

  private static class VariableCellRenderer extends DefaultTableCellRenderer {
    private final List<Variable> myVariables;

    public VariableCellRenderer(List<Variable> variables) {
      this.myVariables = variables;
    }

    public Component getTableCellRendererComponent(JTable table, Object _value,
                                                   boolean isSelected, boolean hasFocus, int row, int column) {
      super.getTableCellRendererComponent(table, _value, isSelected, hasFocus, row, column);
      setForeground(table.getForeground());
      setToolTipText(null);

      for (int i = 0; i < myVariables.size(); i++) {
        Variable variable = myVariables.get(i);
        if (i != row && variable.getName().equals(_value)) {
          setForeground(Color.RED);
          setToolTipText("Duplicate Variable");
        }
        else if (variable.getExpression().length() == 0) {
          setForeground(PlatformColors.BLUE);
          setToolTipText("Empty expression. Variable will evaluate to empty nodeset.");
        }
      }
      return this;
    }
  }

  private static class NamespaceTableModel extends AbstractTableModel {
    private final List<Namespace> myNamespaces;

    public NamespaceTableModel(List<Namespace> namespaces) {
      this.myNamespaces = namespaces;
    }

    public Collection<Namespace> getNamespaces() {
      return myNamespaces;
    }

    public Class<?> getColumnClass(int columnIndex) {
      return String.class;
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return columnIndex == 0;
    }

    public String getColumnName(int column) {
      return column == 0 ? "Prefix" : "URI";
    }

    public int getRowCount() {
      return myNamespaces.size();
    }

    public int getColumnCount() {
      return 2;
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
      final Namespace namespace = myNamespaces.get(rowIndex);
      return columnIndex == 0 ? namespace.getPrefix() : namespace.getUri();
    }

    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
      if (columnIndex == 0) {
        final Namespace namespace = myNamespaces.get(rowIndex);
        namespace.setPrefix((String)aValue);
      }
    }

    public void addNamespace(Namespace namespace) {
      final int firstRow = myNamespaces.size();
      myNamespaces.add(namespace);
      fireTableRowsInserted(firstRow, firstRow);
    }

    public void removeNamespace(int selectedRow) {
      myNamespaces.remove(selectedRow);
      fireTableRowsDeleted(selectedRow, selectedRow);
    }
  }

  private static class NamespaceCellRenderer extends DefaultTableCellRenderer {
    private final List<Namespace> myNamespaces;

    public NamespaceCellRenderer(List<Namespace> namespaces) {
      this.myNamespaces = namespaces;
    }

    public Component getTableCellRendererComponent(JTable table, Object value,
                                                   boolean isSelected, boolean hasFocus, int row, int column) {
      super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
      setForeground(table.getForeground());

      final String prefix = myNamespaces.get(row).getPrefix();
      if (column == 1 && prefix == null || prefix.length() == 0) {
        setForeground(PlatformColors.BLUE);
      }
      else if (column == 0) {
        for (int i = 0; i < myNamespaces.size(); i++) {
          Namespace namespace = myNamespaces.get(i);
          if (i != row && namespace.getPrefix().equals(value)) {
            setForeground(Color.RED);
            break;
          }
        }
      }
      return this;
    }
  }

  private class MyNamespaceContext implements NamespaceContext {
    @Nullable
    public String getNamespaceURI(String prefix, XmlElement context) {
      return Namespace.makeMap(myNamespaceTableModel.getNamespaces()).get(prefix);
    }

    @Nullable
    public String getPrefixForURI(String uri, XmlElement context) {
      final BidirectionalMap<String, String> bidiMap = new BidirectionalMap<String, String>();
      bidiMap.putAll(Namespace.makeMap(myNamespaceTableModel.getNamespaces()));
      final List<String> list = bidiMap.getKeysByValue(uri);
      return list != null && list.size() > 0 ? list.get(0) : null;
    }

    @NotNull
    public Collection<String> getKnownPrefixes(XmlElement context) {
      return Namespace.makeMap(myNamespaceTableModel.getNamespaces()).keySet();
    }

    @Nullable
    public PsiElement resolve(String prefix, XmlElement context) {
      return null;
    }

    public IntentionAction[] getUnresolvedNamespaceFixes(PsiReference reference, String localName) {
      return IntentionAction.EMPTY_ARRAY;
    }

    @Override
    public String getDefaultNamespace(XmlElement context) {
      return null;
    }
  }

  private class MyVariableContext extends SimpleVariableContext {
    @NotNull
    public String[] getVariablesInScope(XPathElement element) {
      final Collection<Variable> variables = myVariableTableModel.getVariables();
      return Variable.asSet(variables).toArray(new String[variables.size()]);
    }
  }

  private class MyContextProvider extends ContextProvider {
    private final MyNamespaceContext myNamespaceContext;
    private final MyVariableContext myVariableContext;
    private final ContextProvider myContextProvider;

    public MyContextProvider(ContextProvider contextProvider) {
      myContextProvider = contextProvider;
      myNamespaceContext = new MyNamespaceContext();
      myVariableContext = new MyVariableContext();
    }

    @NotNull
    public ContextType getContextType() {
      return myContextProvider.getContextType();
    }

    @Nullable
    public XmlElement getContextElement() {
      return myContextProvider.getContextElement();
    }

    @Nullable
    public NamespaceContext getNamespaceContext() {
      return myNamespaceContext;
    }

    @Nullable
    public VariableContext getVariableContext() {
      return myVariableContext;
    }

    @Nullable
    public Set<QName> getAttributes(boolean forValidation) {
      return myContextProvider.getAttributes(forValidation);
    }

    @Nullable
    public Set<QName> getElements(boolean forValidation) {
      return myContextProvider.getElements(forValidation);
    }
  }
}
