// Copyright (C) 2014 The Android Open Source Project
//
// 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 com.google.gerrit.client;

import com.google.gerrit.client.ui.NavigationTable;
import com.google.gerrit.client.ui.OnEditEnabler;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ImageResourceRenderer;
import com.google.gwtexpui.globalkey.client.NpTextBox;
import java.util.ArrayList;
import java.util.List;

public class StringListPanel extends FlowPanel implements HasEnabled {
  private final StringListTable t;
  private HorizontalPanel titlePanel;
  protected final HorizontalPanel buttonPanel;
  private final Button deleteButton;
  private Image info;
  protected FocusWidget widget;

  public StringListPanel(String title, List<String> fieldNames, FocusWidget w, boolean autoSort) {
    widget = w;
    if (title != null) {
      titlePanel = new HorizontalPanel();
      SmallHeading titleLabel = new SmallHeading(title);
      titlePanel.add(titleLabel);
      add(titlePanel);
    }

    t = new StringListTable(fieldNames, autoSort);
    add(t);

    buttonPanel = new HorizontalPanel();
    buttonPanel.setStyleName(Gerrit.RESOURCES.css().stringListPanelButtons());
    deleteButton = new Button(Gerrit.C.stringListPanelDelete());
    deleteButton.setEnabled(false);
    deleteButton.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            widget.setEnabled(true);
            t.deleteChecked();
          }
        });
    buttonPanel.add(deleteButton);
    add(buttonPanel);
  }

  public void display(List<List<String>> values) {
    t.display(values);
  }

  public void setInfo(String msg) {
    if (info == null && titlePanel != null) {
      info = new Image(Gerrit.RESOURCES.info());
      titlePanel.add(info);
    }
    if (info != null) {
      info.setTitle(msg);
    }
  }

  public List<List<String>> getValues() {
    return t.getValues();
  }

  public List<String> getValues(int i) {
    List<List<String>> allValuesList = getValues();
    List<String> singleValueList = new ArrayList<>(allValuesList.size());
    for (List<String> values : allValuesList) {
      singleValueList.add(values.get(i));
    }
    return singleValueList;
  }

  private class StringListTable extends NavigationTable<List<String>> {
    private final Button addButton;
    private final List<NpTextBox> inputs;
    private final boolean autoSort;

    StringListTable(List<String> names, boolean autoSort) {
      this.autoSort = autoSort;

      addButton = new Button(new ImageResourceRenderer().render(Gerrit.RESOURCES.listAdd()));
      addButton.setTitle(Gerrit.C.stringListPanelAdd());
      OnEditEnabler e = new OnEditEnabler(addButton);
      inputs = new ArrayList<>();

      FlexCellFormatter fmt = table.getFlexCellFormatter();
      fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().iconHeader());
      fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().leftMostCell());
      for (int i = 0; i < names.size(); i++) {
        fmt.addStyleName(0, i + 1, Gerrit.RESOURCES.css().dataHeader());
        table.setText(0, i + 1, names.get(i));

        NpTextBox input = new NpTextBox();
        input.setVisibleLength(35);
        input.addKeyPressHandler(
            new KeyPressHandler() {
              @Override
              public void onKeyPress(KeyPressEvent event) {
                if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
                  widget.setEnabled(true);
                  add();
                }
              }
            });
        inputs.add(input);
        fmt.addStyleName(1, i + 1, Gerrit.RESOURCES.css().dataHeader());
        table.setWidget(1, i + 1, input);
        e.listenTo(input);
      }
      addButton.setEnabled(false);

      addButton.addClickHandler(
          new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
              widget.setEnabled(true);
              add();
            }
          });
      fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().iconHeader());
      fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().leftMostCell());
      table.setWidget(1, 0, addButton);

      if (!autoSort) {
        fmt.addStyleName(0, names.size() + 1, Gerrit.RESOURCES.css().iconHeader());
        fmt.addStyleName(0, names.size() + 2, Gerrit.RESOURCES.css().iconHeader());
        fmt.addStyleName(1, names.size() + 1, Gerrit.RESOURCES.css().iconHeader());
        fmt.addStyleName(1, names.size() + 2, Gerrit.RESOURCES.css().iconHeader());
      }
    }

    void display(List<List<String>> values) {
      for (int row = 2; row < table.getRowCount(); row++) {
        table.removeRow(row--);
      }
      int row = 2;
      for (List<String> v : values) {
        populate(row, v);
        row++;
      }
      updateNavigationLinks();
    }

    List<List<String>> getValues() {
      List<List<String>> values = new ArrayList<>();
      for (int row = 2; row < table.getRowCount(); row++) {
        values.add(getRowItem(row));
      }
      return values;
    }

    @Override
    protected List<String> getRowItem(int row) {
      List<String> v = new ArrayList<>();
      for (int i = 0; i < inputs.size(); i++) {
        v.add(table.getText(row, i + 1));
      }
      return v;
    }

    private void populate(int row, List<String> values) {
      FlexCellFormatter fmt = table.getFlexCellFormatter();
      fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().iconCell());
      fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().leftMostCell());
      CheckBox checkBox = new CheckBox();
      checkBox.addValueChangeHandler(
          new ValueChangeHandler<Boolean>() {
            @Override
            public void onValueChange(ValueChangeEvent<Boolean> event) {
              enableDelete();
            }
          });
      table.setWidget(row, 0, checkBox);
      for (int i = 0; i < values.size(); i++) {
        fmt.addStyleName(row, i + 1, Gerrit.RESOURCES.css().dataCell());
        table.setText(row, i + 1, values.get(i));
      }
      if (!autoSort) {
        fmt.addStyleName(row, values.size() + 1, Gerrit.RESOURCES.css().iconCell());
        fmt.addStyleName(row, values.size() + 2, Gerrit.RESOURCES.css().dataCell());

        Image down = new Image(Gerrit.RESOURCES.arrowDown());
        down.setTitle(Gerrit.C.stringListPanelDown());
        down.addClickHandler(
            new ClickHandler() {
              @Override
              public void onClick(ClickEvent event) {
                moveDown(row);
              }
            });
        table.setWidget(row, values.size() + 1, down);

        Image up = new Image(Gerrit.RESOURCES.arrowUp());
        up.setTitle(Gerrit.C.stringListPanelUp());
        up.addClickHandler(
            new ClickHandler() {
              @Override
              public void onClick(ClickEvent event) {
                moveUp(row);
              }
            });
        table.setWidget(row, values.size() + 2, up);
      }
    }

    @Override
    protected void onCellSingleClick(Event event, int row, int column) {
      if (column == inputs.size() + 1 && row >= 2 && row < table.getRowCount() - 2) {
        moveDown(row);
      } else if (column == inputs.size() + 2 && row > 2) {
        moveUp(row);
      }
    }

    void moveDown(int row) {
      if (row < table.getRowCount() - 1) {
        swap(row, row + 1);
      }
    }

    void moveUp(int row) {
      if (row > 2) {
        swap(row - 1, row);
      }
    }

    void swap(int row1, int row2) {
      List<String> value = getRowItem(row1);
      List<String> nextValue = getRowItem(row2);
      populate(row1, nextValue);
      populate(row2, value);
      updateNavigationLinks();
      widget.setEnabled(true);
    }

    private void updateNavigationLinks() {
      if (!autoSort) {
        for (int row = 2; row < table.getRowCount(); row++) {
          table.getWidget(row, inputs.size() + 1).setVisible(row < table.getRowCount() - 1);
          table.getWidget(row, inputs.size() + 2).setVisible(row > 2);
        }
      }
    }

    void add() {
      List<String> values = new ArrayList<>();
      for (NpTextBox input : inputs) {
        values.add(input.getValue().trim());
        input.setValue("");
      }
      insert(values);
    }

    void insert(List<String> v) {
      int insertPos = table.getRowCount();
      if (autoSort) {
        for (int row = 1; row < table.getRowCount(); row++) {
          int compareResult = v.get(0).compareTo(table.getText(row, 1));
          if (compareResult < 0) {
            insertPos = row;
            break;
          } else if (compareResult == 0) {
            return;
          }
        }
      }
      table.insertRow(insertPos);
      populate(insertPos, v);
      updateNavigationLinks();
    }

    void enableDelete() {
      for (int row = 2; row < table.getRowCount(); row++) {
        if (((CheckBox) table.getWidget(row, 0)).getValue()) {
          deleteButton.setEnabled(true);
          return;
        }
      }
      deleteButton.setEnabled(false);
    }

    void deleteChecked() {
      deleteButton.setEnabled(false);
      for (int row = 2; row < table.getRowCount(); row++) {
        if (((CheckBox) table.getWidget(row, 0)).getValue()) {
          table.removeRow(row--);
        }
      }
      updateNavigationLinks();
    }

    @Override
    protected void onOpenRow(int row) {}

    @Override
    protected Object getRowItemKey(List<String> item) {
      return item.get(0);
    }

    void setEnabled(boolean enabled) {
      addButton.setVisible(enabled);
      for (NpTextBox input : inputs) {
        input.setEnabled(enabled);
      }
      for (int row = 2; row < table.getRowCount(); row++) {
        table.getWidget(row, 0).setVisible(enabled);
        if (!autoSort) {
          table.getWidget(row, inputs.size() + 1).setVisible(enabled);
          table.getWidget(row, inputs.size() + 2).setVisible(enabled);
        }
      }
      if (enabled) {
        updateNavigationLinks();
      }
    }
  }

  @Override
  public boolean isEnabled() {
    return deleteButton.isVisible();
  }

  @Override
  public void setEnabled(boolean enabled) {
    t.setEnabled(enabled);
    deleteButton.setVisible(enabled);
  }
}
