package com.intellij.updater;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

public class SwingUpdaterUI implements UpdaterUI {
  static final int RESULT_REQUIRES_RESTART = 42;

  private static final EmptyBorder FRAME_BORDER = new EmptyBorder(8, 8, 8, 8);
  private static final EmptyBorder LABEL_BORDER = new EmptyBorder(0, 0, 5, 0);
  private static final EmptyBorder BUTTONS_BORDER = new EmptyBorder(5, 0, 0, 0);

  private static final String TITLE = "Update";

  private static final String CANCEL_BUTTON_TITLE = "Cancel";
  private static final String EXIT_BUTTON_TITLE = "Exit";

  private static final String PROCEED_BUTTON_TITLE = "Proceed";

  private final int mySuccessExitCode;
  private final InstallOperation myOperation;

  private final JLabel myProcessTitle;
  private final JProgressBar myProcessProgress;
  private final JLabel myProcessStatus;
  private final JTextArea myConsole;
  private final JPanel myConsolePane;

  private final JButton myRetryButton;
  private final JButton myCancelButton;

  private final ConcurrentLinkedQueue<UpdateRequest> myQueue = new ConcurrentLinkedQueue<UpdateRequest>();
  private final AtomicBoolean isCancelled = new AtomicBoolean(false);
  private final AtomicBoolean isRunning = new AtomicBoolean(false);
  private final AtomicBoolean hasError = new AtomicBoolean(false);
  private final AtomicBoolean hasRetry = new AtomicBoolean(false);
  private final JFrame myFrame;
  private boolean myApplied;

  /**
   * Displays the updater UI and asynchronously runs the operation list.
   *
   * @param oldBuildDesc The old build description, for display purposes.
   * @param newBuildDesc The new build description, for display purposes.
   * @param successExitCode The desired exit code on success. Default is {@link #RESULT_REQUIRES_RESTART}.
   * @param operation The install operations to perform.
   */
  public SwingUpdaterUI(String oldBuildDesc,
                        String newBuildDesc,
                        int successExitCode,
                        InstallOperation operation) {
    mySuccessExitCode = successExitCode;
    myOperation = operation;

    myProcessTitle = new JLabel(" ");
    myProcessProgress = new JProgressBar(0, 100);
    myProcessStatus = new JLabel(" ");

    myCancelButton = new JButton(CANCEL_BUTTON_TITLE);

    myRetryButton = new JButton("Retry");
    myRetryButton.setEnabled(false);
    myRetryButton.setVisible(false);

    myConsole = new JTextArea();
    myConsole.setLineWrap(true);
    myConsole.setWrapStyleWord(true);
    myConsole.setCaretPosition(myConsole.getText().length());
    myConsole.setTabSize(1);
    myConsole.setMargin(new Insets(2, 4, 2, 4));
    myConsolePane = new JPanel(new BorderLayout());
    myConsolePane.add(new JScrollPane(myConsole));
    myConsolePane.setBorder(BUTTONS_BORDER);
    myConsolePane.setVisible(false);

    myCancelButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        doCancel();
      }
    });

    myRetryButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        doRetry();
      }
    });

    myFrame = new JFrame();
    myFrame.setTitle(TITLE);

    myFrame.setLayout(new BorderLayout());
    myFrame.getRootPane().setBorder(FRAME_BORDER);
    myFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

    myFrame.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent e) {
        doCancel();
      }
    });

    JPanel processPanel = new JPanel();
    processPanel.setLayout(new BoxLayout(processPanel, BoxLayout.Y_AXIS));
    processPanel.add(myProcessTitle);
    processPanel.add(myProcessProgress);
    processPanel.add(myProcessStatus);

    processPanel.add(myConsolePane);
    for (Component each : processPanel.getComponents()) {
      ((JComponent)each).setAlignmentX(Component.LEFT_ALIGNMENT);
    }

    JPanel buttonsPanel = new JPanel();
    buttonsPanel.setBorder(BUTTONS_BORDER);
    buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
    buttonsPanel.add(Box.createHorizontalGlue());
    buttonsPanel.add(myRetryButton);
    buttonsPanel.add(myCancelButton);

    myProcessTitle.setText("<html>Updating " + oldBuildDesc + " to " + newBuildDesc + "...");

    myFrame.add(processPanel, BorderLayout.CENTER);
    myFrame.add(buttonsPanel, BorderLayout.SOUTH);

    myFrame.setMinimumSize(new Dimension(500, 50));
    myFrame.pack();
    myFrame.setLocationRelativeTo(null);

    myFrame.setVisible(true);

    myQueue.add(new UpdateRequest() {
      @Override
      public void perform() {
        doPerform();
      }
    });

    startRequestDispatching();
  }

  private void startRequestDispatching() {
    new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
          try {
            Thread.sleep(100);
          }
          catch (InterruptedException e) {
            Runner.printStackTrace(e);
            return;
          }

          final List<UpdateRequest> pendingRequests = new ArrayList<UpdateRequest>();
          UpdateRequest request;
          while ((request = myQueue.poll()) != null) {
            pendingRequests.add(request);
          }

          SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
              for (UpdateRequest each : pendingRequests) {
                each.perform();
              }
            }
          });
        }
      }
    }).start();
  }

  private void doCancel() {
    if (isRunning.get()) {
      int result = JOptionPane.showConfirmDialog(myFrame,
                                                 "The patch has not been applied yet.\nAre you sure you want to abort the operation?",
                                                 TITLE, JOptionPane.YES_NO_OPTION);
      if (result == JOptionPane.YES_OPTION) {
        isCancelled.set(true);
        myCancelButton.setEnabled(false);
      }
    }
    else {
      exit();
    }
  }

  private void doRetry() {
    hasError.set(false);
    hasRetry.set(false);
    isCancelled.set(false);
    myQueue.add(new UpdateRequest() {
      @Override
      public void perform() {
        myConsole.setText("");
        myConsolePane.setVisible(false);
        myConsolePane.setPreferredSize(new Dimension(10, 200));
        myRetryButton.setEnabled(false);
        myCancelButton.setEnabled(true);
      }
    });
    doPerform();
  }

  private void doPerform() {
    isRunning.set(true);

    new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          myApplied = myOperation.execute(SwingUpdaterUI.this);
        }
        catch (OperationCancelledException ignore) {
          Runner.printStackTrace(ignore);
        }
        catch(Throwable e) {
          Runner.printStackTrace(e);
          showError(e);
        }
        finally {
          isRunning.set(false);

          if (hasRetry.get()) {
            myRetryButton.setVisible(true);
            myRetryButton.setEnabled(true);
          }
          if (hasError.get()) {
            startProcess("Failed to apply patch");
            setProgress(100);
            myCancelButton.setText(EXIT_BUTTON_TITLE);
            myCancelButton.setEnabled(true);
          } else {
            exit();
          }
        }
      }
    }).start();
  }

  private void exit() {
    System.exit(myApplied ? mySuccessExitCode : 0);
  }

  @Override
  public Map<String, ValidationResult.Option> askUser(final List<ValidationResult> validationResults) throws OperationCancelledException {
    if (validationResults.isEmpty()) return Collections.emptyMap();

    final Map<String, ValidationResult.Option> result = new HashMap<String, ValidationResult.Option>();
    try {
      SwingUtilities.invokeAndWait(new Runnable() {
        @Override
        public void run() {
          final JDialog dialog = new JDialog(myFrame, TITLE, true);
          dialog.setLayout(new BorderLayout());
          dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);

          JPanel buttonsPanel = new JPanel();
          buttonsPanel.setBorder(BUTTONS_BORDER);
          buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
          buttonsPanel.add(Box.createHorizontalGlue());
          JButton proceedButton = new JButton(PROCEED_BUTTON_TITLE);
          proceedButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              dialog.setVisible(false);
            }
          });

          JButton cancelButton = new JButton(CANCEL_BUTTON_TITLE);
          cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              isCancelled.set(true);
              myCancelButton.setEnabled(false);
              dialog.setVisible(false);
            }
          });

          buttonsPanel.add(proceedButton);
          buttonsPanel.add(cancelButton);

          dialog.getRootPane().setDefaultButton(proceedButton);

          JTable table = new JTable();

          table.setCellSelectionEnabled(true);
          table.setDefaultEditor(ValidationResult.Option.class, new MyCellEditor());
          table.setDefaultRenderer(Object.class, new MyCellRenderer());
          MyTableModel model = new MyTableModel(validationResults);
          table.setModel(model);

          for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) {
            TableColumn each = table.getColumnModel().getColumn(i);
            each.setPreferredWidth(MyTableModel.getColumnWidth(i, new Dimension(600, 400).width));
          }

          String message = "<html>There are some conflicts found in the installation.<br><br>" +
                           "Please select desired solutions from the " + MyTableModel.COLUMNS[MyTableModel.OPTIONS_COLUMN_INDEX] +
                           " column and press " + PROCEED_BUTTON_TITLE + ".<br>" +
                           "If you do not want to proceed with the update, please press " + CANCEL_BUTTON_TITLE + ".</html>";

          JLabel label = new JLabel(message);
          label.setBorder(LABEL_BORDER);
          dialog.add(label, BorderLayout.NORTH);
          dialog.add(new JScrollPane(table), BorderLayout.CENTER);
          dialog.add(buttonsPanel, BorderLayout.SOUTH);

          dialog.getRootPane().setBorder(FRAME_BORDER);

          dialog.setSize(new Dimension(600, 400));
          dialog.setLocationRelativeTo(null);
          dialog.setVisible(true);

          result.putAll(model.getResult());
        }
      });
    }
    catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
    catch (InvocationTargetException e) {
      throw new RuntimeException(e);
    }
    checkCancelled();
    return result;
  }

  @Override
  public void startProcess(final String title) {
    myQueue.add(new UpdateRequest() {
      @Override
      public void perform() {
        myProcessStatus.setText(title);
        myProcessProgress.setIndeterminate(false);
        myProcessProgress.setValue(0);
      }
    });
  }

  @Override
  public void setProgress(final int percentage) {
    myQueue.add(new UpdateRequest() {
      @Override
      public void perform() {
        myProcessProgress.setIndeterminate(false);
        myProcessProgress.setValue(percentage);
      }
    });
  }

  @Override
  public void setProgressIndeterminate() {
    myQueue.add(new UpdateRequest() {
      @Override
      public void perform() {
        myProcessProgress.setIndeterminate(true);
      }
    });
  }

  @Override
  public void setStatus(final String status) {
  }

  @Override
  public void showError(final Throwable e) {
    hasError.set(true);
    StringWriter w = new StringWriter();

    if (e instanceof RetryException) {
      hasRetry.set(true);

      w.write("+----------------\n");
      w.write("| A file operation failed.\n");
      w.write("| This might be due to a file being locked by another\n");
      w.write("| application. Please try closing any application\n");
      w.write("| that uses the files being updated then press 'Retry'.\n");
      w.write("+----------------\n");
      w.write("\n\n");
    }

    e.printStackTrace(new PrintWriter(w));

    final String content = w.getBuffer().toString();

    myQueue.add(new UpdateRequest() {
      @Override
      public void perform() {
        StringWriter w = new StringWriter();
        if (!myConsolePane.isVisible()) {
          w.write("Temp. directory: ");
          w.write(System.getProperty("java.io.tmpdir"));
          w.write("\n\n");
        }
        myConsole.append(w.getBuffer().toString());
        myConsole.append(content);
        if (!myConsolePane.isVisible()) {
          myConsole.setCaretPosition(0);
          myConsolePane.setVisible(true);
          myConsolePane.setPreferredSize(new Dimension(10, 200));
          myFrame.pack();
        }
      }
    });
  }

  @Override
  public void checkCancelled() throws OperationCancelledException {
    if (isCancelled.get()) throw new OperationCancelledException();
  }

  public interface InstallOperation {
    boolean execute(UpdaterUI ui) throws OperationCancelledException;
  }

  private interface UpdateRequest {
    void perform();
  }

  public static void main(String[] args) {
    new SwingUpdaterUI("xxx", "yyy", RESULT_REQUIRES_RESTART, new InstallOperation() {
      @Override
      public boolean execute(UpdaterUI ui) throws OperationCancelledException {
        ui.startProcess("Process1");
        ui.checkCancelled();
        for (int i = 0; i < 200; i++) {
          ui.setStatus("i = " + i);
          ui.checkCancelled();
          try {
            Thread.sleep(10);
          }
          catch (InterruptedException e) {
            throw new RuntimeException(e);
          }
          ui.setProgress((i + 1) * 100 / 200);
        }

        ui.showError(new Throwable());

        ui.startProcess("Process3");
        ui.checkCancelled();
        ui.setProgressIndeterminate();
        try {
          for (int i = 0; i < 200; i++) {
            ui.setStatus("i = " + i);
            ui.checkCancelled();
            try {
              Thread.sleep(10);
            }
            catch (InterruptedException e) {
              throw new RuntimeException(e);
            }
            ui.setProgress((i + 1) * 100 / 200);
            if (i == 100) {
              List<ValidationResult> vr = new ArrayList<ValidationResult>();
              vr.add(new ValidationResult(ValidationResult.Kind.ERROR,
                                          "foo/bar",
                                          ValidationResult.Action.CREATE,
                                          "Hello",
                                          ValidationResult.Option.REPLACE,
                                          ValidationResult.Option.KEEP));
              vr.add(new ValidationResult(ValidationResult.Kind.CONFLICT,
                                          "foo/bar/baz",
                                          ValidationResult.Action.DELETE,
                                          "World",
                                          ValidationResult.Option.DELETE,
                                          ValidationResult.Option.KEEP));
              vr.add(new ValidationResult(ValidationResult.Kind.INFO,
                                          "xxx",
                                          ValidationResult.Action.NO_ACTION,
                                          "bla-bla",
                                          ValidationResult.Option.IGNORE));
              ui.askUser(vr);
            }
          }
        }
        finally {
          ui.startProcess("Process2");
          for (int i = 0; i < 200; i++) {
            ui.setStatus("i = " + i);
            try {
              Thread.sleep(10);
            }
            catch (InterruptedException e) {
              throw new RuntimeException(e);
            }
            ui.setProgress((i + 1) * 100 / 200);
          }
        }
        return true;
      }
    });
  }

  private static class MyTableModel extends AbstractTableModel {
    public static final String[] COLUMNS = new String[]{"File", "Action", "Problem", "Solution"};
    public static final int OPTIONS_COLUMN_INDEX = 3;
    private final List<Item> myItems = new ArrayList<Item>();

    public MyTableModel(List<ValidationResult> validationResults) {
      for (ValidationResult each : validationResults) {
        myItems.add(new Item(each, each.options.get(0)));
      }
    }

    @Override
    public int getColumnCount() {
      return COLUMNS.length;
    }

    @Override
    public String getColumnName(int column) {
      return COLUMNS[column];
    }

    public static int getColumnWidth(int column, int totalWidth) {
      switch (column) {
        case 0:
          return (int)(totalWidth * 0.6);
        default:
          return (int)(totalWidth * 0.15);
      }
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
      if (columnIndex == OPTIONS_COLUMN_INDEX) {
        return ValidationResult.Option.class;
      }
      return super.getColumnClass(columnIndex);
    }

    @Override
    public int getRowCount() {
      return myItems.size();
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return columnIndex == OPTIONS_COLUMN_INDEX && getOptions(rowIndex).size() > 1;
    }

    @Override
    public void setValueAt(Object value, int rowIndex, int columnIndex) {
      if (columnIndex == OPTIONS_COLUMN_INDEX) {
        myItems.get(rowIndex).option = (ValidationResult.Option)value;
      }
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
      Item item = myItems.get(rowIndex);
      switch (columnIndex) {
        case 0:
          return item.validationResult.path;
        case 1:
          return item.validationResult.action;
        case 2:
          return item.validationResult.message;
        case OPTIONS_COLUMN_INDEX:
          return item.option;
      }
      return null;
    }

    public ValidationResult.Kind getKind(int rowIndex) {
      return myItems.get(rowIndex).validationResult.kind;
    }

    public List<ValidationResult.Option> getOptions(int rowIndex) {
      Item item = myItems.get(rowIndex);
      return item.validationResult.options;
    }

    public Map<String, ValidationResult.Option> getResult() {
      Map<String, ValidationResult.Option> result = new HashMap<String, ValidationResult.Option>();
      for (Item each : myItems) {
        result.put(each.validationResult.path, each.option);
      }
      return result;
    }

    private static class Item {
      ValidationResult validationResult;
      ValidationResult.Option option;

      private Item(ValidationResult validationResult, ValidationResult.Option option) {
        this.validationResult = validationResult;
        this.option = option;
      }
    }
  }

  private static class MyCellEditor extends DefaultCellEditor {
    public MyCellEditor() {
      super(new JComboBox());
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
      MyTableModel tableModel = (MyTableModel)table.getModel();
      DefaultComboBoxModel comboModel = new DefaultComboBoxModel();

      for (ValidationResult.Option each : tableModel.getOptions(row)) {
        comboModel.addElement(each);
      }
      ((JComboBox)editorComponent).setModel(comboModel);

      return super.getTableCellEditorComponent(table, value, isSelected, row, column);
    }
  }

  private static class MyCellRenderer extends DefaultTableCellRenderer {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      Component result = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
      if (!isSelected) {
        MyTableModel tableModel = (MyTableModel)table.getModel();
        Color color = table.getBackground();

        switch (tableModel.getKind(row)) {
          case ERROR:
            color = new Color(255, 175, 175);
            break;
          case CONFLICT:
            color = new Color(255, 240, 240);
            break;
        }
        result.setBackground(color);
      }
      return result;
    }
  }
}
