/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.lucene.luke.app.desktop.components.dialog.documents;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.Window;
import java.io.IOException;
import java.util.Arrays;

import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableFieldType;
import org.apache.lucene.luke.app.desktop.Preferences;
import org.apache.lucene.luke.app.desktop.PreferencesFactory;
import org.apache.lucene.luke.app.desktop.dto.documents.NewField;
import org.apache.lucene.luke.app.desktop.util.DialogOpener;
import org.apache.lucene.luke.app.desktop.util.MessageUtils;

/** Factory of index options dialog */
public final class IndexOptionsDialogFactory implements DialogOpener.DialogFactory {

  private static IndexOptionsDialogFactory instance;

  private final Preferences prefs;

  private final JCheckBox storedCB = new JCheckBox();

  private final JCheckBox tokenizedCB = new JCheckBox();

  private final JCheckBox omitNormsCB = new JCheckBox();

  private final JComboBox<String> idxOptCombo = new JComboBox<>(availableIndexOptions());

  private final JCheckBox storeTVCB = new JCheckBox();

  private final JCheckBox storeTVPosCB = new JCheckBox();

  private final JCheckBox storeTVOffCB = new JCheckBox();

  private final JCheckBox storeTVPayCB = new JCheckBox();

  private final JComboBox<String> dvTypeCombo = new JComboBox<>(availableDocValuesType());

  private final JTextField dimCountTF = new JTextField();

  private final JTextField dimNumBytesTF = new JTextField();

  private JDialog dialog;

  private NewField nf;

  public synchronized static IndexOptionsDialogFactory getInstance() throws IOException {
    if (instance == null) {
      instance = new IndexOptionsDialogFactory();
    }
    return instance;
  }

  private IndexOptionsDialogFactory() throws IOException {
    this.prefs = PreferencesFactory.getInstance();
    initialize();
  }

  private void initialize() {
    storedCB.setText(MessageUtils.getLocalizedMessage("idx_options.checkbox.stored"));
    storedCB.setOpaque(false);
    tokenizedCB.setText(MessageUtils.getLocalizedMessage("idx_options.checkbox.tokenized"));
    tokenizedCB.setOpaque(false);
    omitNormsCB.setText(MessageUtils.getLocalizedMessage("idx_options.checkbox.omit_norm"));
    omitNormsCB.setOpaque(false);
    idxOptCombo.setPreferredSize(new Dimension(300, idxOptCombo.getPreferredSize().height));
    storeTVCB.setText(MessageUtils.getLocalizedMessage("idx_options.checkbox.store_tv"));
    storeTVCB.setOpaque(false);
    storeTVPosCB.setText(MessageUtils.getLocalizedMessage("idx_options.checkbox.store_tv_pos"));
    storeTVPosCB.setOpaque(false);
    storeTVOffCB.setText(MessageUtils.getLocalizedMessage("idx_options.checkbox.store_tv_off"));
    storeTVOffCB.setOpaque(false);
    storeTVPayCB.setText(MessageUtils.getLocalizedMessage("idx_options.checkbox.store_tv_pay"));
    storeTVPayCB.setOpaque(false);
    dimCountTF.setColumns(4);
    dimNumBytesTF.setColumns(4);
  }

  @Override
  public JDialog create(Window owner, String title, int width, int height) {
    dialog = new JDialog(owner, title, Dialog.ModalityType.APPLICATION_MODAL);
    dialog.add(content());
    dialog.setSize(new Dimension(width, height));
    dialog.setLocationRelativeTo(owner);
    dialog.getContentPane().setBackground(prefs.getColorTheme().getBackgroundColor());
    return dialog;
  }

  private JPanel content() {
    JPanel panel = new JPanel();
    panel.setOpaque(false);
    panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

    panel.add(indexOptions());
    panel.add(new JSeparator(JSeparator.HORIZONTAL));
    panel.add(tvOptions());
    panel.add(new JSeparator(JSeparator.HORIZONTAL));
    panel.add(dvOptions());
    panel.add(new JSeparator(JSeparator.HORIZONTAL));
    panel.add(pvOptions());
    panel.add(new JSeparator(JSeparator.HORIZONTAL));
    panel.add(footer());
    return panel;
  }

  private JPanel indexOptions() {
    JPanel panel = new JPanel();
    panel.setOpaque(false);
    panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));

    JPanel inner1 = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 5));
    inner1.setOpaque(false);
    inner1.add(storedCB);

    inner1.add(tokenizedCB);
    inner1.add(omitNormsCB);
    panel.add(inner1);

    JPanel inner2 = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 1));
    inner2.setOpaque(false);
    JLabel idxOptLbl = new JLabel(MessageUtils.getLocalizedMessage("idx_options.label.index_options"));
    inner2.add(idxOptLbl);
    inner2.add(idxOptCombo);
    panel.add(inner2);

    return panel;
  }

  private JPanel tvOptions() {
    JPanel panel = new JPanel();
    panel.setOpaque(false);
    panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));

    JPanel inner1 = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 2));
    inner1.setOpaque(false);
    inner1.add(storeTVCB);
    panel.add(inner1);

    JPanel inner2 = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 2));
    inner2.setOpaque(false);
    inner2.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
    inner2.add(storeTVPosCB);
    inner2.add(storeTVOffCB);
    inner2.add(storeTVPayCB);
    panel.add(inner2);

    return panel;
  }

  private JPanel dvOptions() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 2));
    panel.setOpaque(false);
    JLabel dvTypeLbl = new JLabel(MessageUtils.getLocalizedMessage("idx_options.label.dv_type"));
    panel.add(dvTypeLbl);
    panel.add(dvTypeCombo);
    return panel;
  }

  private JPanel pvOptions() {
    JPanel panel = new JPanel();
    panel.setOpaque(false);
    panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));

    JPanel inner1 = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 2));
    inner1.setOpaque(false);
    inner1.add(new JLabel(MessageUtils.getLocalizedMessage("idx_options.label.point_dims")));
    panel.add(inner1);

    JPanel inner2 = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 2));
    inner2.setOpaque(false);
    inner2.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
    inner2.add(new JLabel(MessageUtils.getLocalizedMessage("idx_options.label.point_dc")));
    inner2.add(dimCountTF);
    inner2.add(new JLabel(MessageUtils.getLocalizedMessage("idx_options.label.point_nb")));
    inner2.add(dimNumBytesTF);
    panel.add(inner2);

    return panel;
  }

  private JPanel footer() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
    panel.setOpaque(false);
    JButton okBtn = new JButton(MessageUtils.getLocalizedMessage("button.ok"));
    okBtn.setMargin(new Insets(3, 3, 3, 3));
    okBtn.addActionListener(e -> saveOptions());
    panel.add(okBtn);
    JButton cancelBtn = new JButton(MessageUtils.getLocalizedMessage("button.cancel"));
    cancelBtn.setMargin(new Insets(3, 3, 3, 3));
    cancelBtn.addActionListener(e -> dialog.dispose());
    panel.add(cancelBtn);

    return panel;
  }

  // control methods

  public void setNewField(NewField nf) {
    this.nf = nf;

    storedCB.setSelected(nf.isStored());

    IndexableFieldType fieldType = nf.getFieldType();
    tokenizedCB.setSelected(fieldType.tokenized());
    omitNormsCB.setSelected(fieldType.omitNorms());
    idxOptCombo.setSelectedItem(fieldType.indexOptions().name());
    storeTVCB.setSelected(fieldType.storeTermVectors());
    storeTVPosCB.setSelected(fieldType.storeTermVectorPositions());
    storeTVOffCB.setSelected(fieldType.storeTermVectorOffsets());
    storeTVPayCB.setSelected(fieldType.storeTermVectorPayloads());
    dvTypeCombo.setSelectedItem(fieldType.docValuesType().name());
    dimCountTF.setText(String.valueOf(fieldType.pointDimensionCount()));
    dimNumBytesTF.setText(String.valueOf(fieldType.pointNumBytes()));

    if (nf.getType().equals(org.apache.lucene.document.TextField.class) ||
        nf.getType().equals(StringField.class) ||
        nf.getType().equals(Field.class)) {
      storedCB.setEnabled(true);
    } else {
      storedCB.setEnabled(false);
    }

    if (nf.getType().equals(Field.class)) {
      tokenizedCB.setEnabled(true);
      omitNormsCB.setEnabled(true);
      idxOptCombo.setEnabled(true);
      storeTVCB.setEnabled(true);
      storeTVPosCB.setEnabled(true);
      storeTVOffCB.setEnabled(true);
      storeTVPosCB.setEnabled(true);
    } else {
      tokenizedCB.setEnabled(false);
      omitNormsCB.setEnabled(false);
      idxOptCombo.setEnabled(false);
      storeTVCB.setEnabled(false);
      storeTVPosCB.setEnabled(false);
      storeTVOffCB.setEnabled(false);
      storeTVPayCB.setEnabled(false);
    }

    // TODO
    dvTypeCombo.setEnabled(false);
    dimCountTF.setEnabled(false);
    dimNumBytesTF.setEnabled(false);
  }

  private void saveOptions() {
    nf.setStored(storedCB.isSelected());
    if (nf.getType().equals(Field.class)) {
      FieldType ftype = (FieldType) nf.getFieldType();
      ftype.setStored(storedCB.isSelected());
      ftype.setTokenized(tokenizedCB.isSelected());
      ftype.setOmitNorms(omitNormsCB.isSelected());
      ftype.setIndexOptions(IndexOptions.valueOf((String) idxOptCombo.getSelectedItem()));
      ftype.setStoreTermVectors(storeTVCB.isSelected());
      ftype.setStoreTermVectorPositions(storeTVPosCB.isSelected());
      ftype.setStoreTermVectorOffsets(storeTVOffCB.isSelected());
      ftype.setStoreTermVectorPayloads(storeTVPayCB.isSelected());
    }
    dialog.dispose();
  }

  private static String[] availableIndexOptions() {
    return Arrays.stream(IndexOptions.values()).map(IndexOptions::name).toArray(String[]::new);
  }

  private static String[] availableDocValuesType() {
    return Arrays.stream(DocValuesType.values()).map(DocValuesType::name).toArray(String[]::new);
  }

}
