/**
 * Copyright (C) 2004-2011 Jive Software. All rights reserved.
 *
 * 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.jivesoftware.sparkimpl.plugin.scratchpad;

import java.time.Instant;
import java.time.ZonedDateTime;

import org.jdesktop.swingx.JXDatePicker;
import org.jivesoftware.resource.Default;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.RolloverButton;
import org.jivesoftware.spark.component.VerticalFlowLayout;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.ui.ContactList;
import org.jivesoftware.spark.util.*;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.sparkimpl.plugin.manager.Enterprise;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimerTask;

/**
 * Allows users to have scratch paper within Spark.
 */
public class ScratchPadPlugin implements Plugin {

    public static boolean SHOW_ALL_TASKS = true;

    private static final String dateShortFormat = ((SimpleDateFormat)SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT)).toPattern();
    private final SimpleDateFormat formatter = new SimpleDateFormat(dateShortFormat);
    private static final List<TaskUI> taskList = new ArrayList<>();
    private static JPanel panel_events;
    private static JPanel mainPanel;
    private static JFrame frame;

    private static final Color COLOR_GRADIENT = new Color(198, 211, 247);

    @Override
	public void initialize() {
            TimerTask startTask = new TimerTask() {
                @Override
                public void run() {
                    EventQueue.invokeLater(() -> {
                        panel_events = new JPanel();
                        mainPanel = new JPanel();
                    });
                }
            };

            TaskEngine.getInstance().schedule(startTask, 500);

            ContactList contactList = SparkManager.getWorkspace().getContactList();
            contactList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F6"), "viewNotes");

            contactList.getActionMap().put("viewNotes", new AbstractAction("viewNotes") {
                @Override
				public void actionPerformed(ActionEvent evt) {
                    // Retrieve notes and display in editor.
                    retrieveNotes();
                }
            });

            contactList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control F5"), "viewTasks");

            contactList.getActionMap().put("viewTasks", new AbstractAction("viewTasks") {
                @Override
				public void actionPerformed(ActionEvent evt) {
                    // Retrieve notes and display in editor.
                    showTaskList();
                }
            });

            JMenuItem taskMenu = new JMenuItem(Res.getString("button.view.tasklist"), SparkRes.getImageIcon(SparkRes.Icon.DESKTOP_IMAGE));
            taskMenu.addActionListener(e -> showTaskList());

            JMenuItem notesMenu = new JMenuItem(Res.getString("button.view.notes"), SparkRes.getImageIcon(SparkRes.Icon.DOCUMENT_16x16));
            notesMenu.addActionListener(e -> retrieveNotes());

            // Add To toolbar
            final JMenu actionsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions"));
            actionsMenu.addSeparator();

            // See if we should disable the "View task list" option under "Actions"
            if (!Default.getBoolean(Default.DISABLE_VIEW_TASK_LIST) && Enterprise.containsFeature(Enterprise.VIEW_TASKS_FEATURE)) actionsMenu.add(taskMenu);

            // See if we should disable the "View notes" option under "Actions"
            if (!Default.getBoolean(Default.DISABLE_VIEW_NOTES) && Enterprise.containsFeature(Enterprise.VIEW_NOTES_FEATURE)) actionsMenu.add(notesMenu);

            // Start notifications.
            new TaskNotification();
        }


    private void showTaskList() {
        frame = new JFrame(Res.getString("title.tasks"));
        frame.setIconImage(SparkManager.getMainWindow().getIconImage());
        panel_events.removeAll();
        mainPanel.removeAll();

        mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
        mainPanel.setBackground(Color.white);

        final JPanel topPanel = new JPanel(new GridBagLayout());
        final JTextField taskField = new JTextField();
        final JXDatePicker dueDateField = new JXDatePicker();
        dueDateField.getMonthView().setLowerBound(new Date());
        dueDateField.setPreferredSize(new Dimension(75, 25));

        final JButton addButton = new JButton(Res.getString("add"));
        final JLabel addTaskLabel = new JLabel(Res.getString("label.add.task"));
        topPanel.setOpaque(false);

        topPanel.add(addTaskLabel, new GridBagConstraints(0, 0, 1, 1, .9, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0));
        topPanel.add(taskField, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 0, 2), 0, 0));

        topPanel.add(dueDateField, new GridBagConstraints(1, 1, 1, 1, 0.1, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 0, 2), 50, 0));
        topPanel.add(addButton, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 0, 2), 0, 0));
        mainPanel.add(topPanel);

        // Add Selection
        final JPanel middlePanel = new JPanel(new GridBagLayout());
        final JLabel showLabel = new JLabel(Res.getString("label.show"));
        final JToggleButton allButton = new JToggleButton(Res.getString("button.tasks.all"));
        final JToggleButton activeButton = new JToggleButton(Res.getString("button.tasks.active"));
        final ButtonGroup buttonGroup = new ButtonGroup();
        buttonGroup.add(allButton);
        buttonGroup.add(activeButton);
        middlePanel.setOpaque(false);

        middlePanel.add(showLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0));
        middlePanel.add(allButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0));
        middlePanel.add(activeButton, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0));

        mainPanel.add(middlePanel);
        mainPanel.setBackground(Color.white);

        final JPanel titlePanel = new JPanel(new BorderLayout()) {
	    @Override
		public void paintComponent(Graphics g) {
                Color startColor = Color.white;
                Color endColor = COLOR_GRADIENT;

                Graphics2D g2 = (Graphics2D)g;

                int w = getWidth();
                int h = getHeight();

                GradientPaint gradient = new GradientPaint(0, 0, startColor, w, h, endColor, true);
                g2.setPaint(gradient);
                g2.fillRect(0, 0, w, h);
            }

        };
        final JLabel taskLabel = new JLabel(Res.getString("label.due") + "        ");
        taskLabel.setFont(taskLabel.getFont().deriveFont(Font.BOLD));
        titlePanel.add(taskLabel, BorderLayout.EAST);
        mainPanel.add(titlePanel);

        Action showAllAction = new AbstractAction() {
	    @Override
		public void actionPerformed(ActionEvent e) {
                for (TaskUI ui : taskList) {
                    ui.setVisible(true);
                }
                SHOW_ALL_TASKS = true;
            }
        };

        Action showActiveAction = new AbstractAction() {
	    @Override
		public void actionPerformed(ActionEvent e) {
                for (TaskUI ui : taskList) {
                    if (ui.isSelected()) {
                        ui.setVisible(false);
                    }
                }
                SHOW_ALL_TASKS = false;
            }
        };

        final Action addAction = new AbstractAction() {
	    @Override
		public void actionPerformed(ActionEvent e) {
                String taskTitle = taskField.getText();
                if (!ModelUtil.hasLength(taskTitle)) {
                    return;
                }
                Task task = new Task();
                task.setTitle(taskTitle);
                // Set creation time.
                final Date creationDate = new Date();
                task.setCreatedDate(creationDate.getTime());
                // Set due date.
            Date dueDate = dueDateField.getDate();
            if (dueDate != null) {
                task.setDueDate(dueDate.getTime());
            }

                taskField.setText("");

                final TaskUI taskUI = new TaskUI(task);
                //mainPanel.add(taskUI);
                panel_events.add(taskUI);
                taskList.add(taskUI);
                
                panel_events.invalidate();
                panel_events.validate();
                panel_events.repaint();                
                mainPanel.invalidate();
                mainPanel.validate();
                mainPanel.repaint();
                frame.invalidate();
                frame.validate();
                frame.repaint();                
            }
        };
        
        mainPanel.add(panel_events);
        panel_events.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
        panel_events.setBackground(Color.white);
        
        allButton.addActionListener(showAllAction);
        activeButton.addActionListener(showActiveAction);

        GraphicUtils.makeSameSize(allButton, activeButton);

        addButton.addActionListener(addAction);

        Tasks tasks = Tasks.getTaskList();
        SHOW_ALL_TASKS = tasks.isShowAll();
        updateTaskUI(tasks);

        if (SHOW_ALL_TASKS) {
            allButton.setSelected(true);
        }
        else {
            activeButton.setSelected(true);
            showActiveAction.actionPerformed(null);
        }

        Instant tomorrow = ZonedDateTime.now().plusDays(1).toInstant();
        dueDateField.setDate(Date.from(tomorrow));

        final JScrollPane pane = new JScrollPane(mainPanel);

        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(pane, BorderLayout.CENTER);
        frame.pack();
        frame.setSize(400, 400);

        final Action saveAction = new AbstractAction() {
	    @Override
		public void actionPerformed(ActionEvent actionEvent) {
                // Save it.
                Tasks tasks = new Tasks();
                tasks.setShowAll(SHOW_ALL_TASKS);
                for (TaskUI ui : taskList) {
                    Task task = ui.getTask();
                    tasks.addTask(task);
                }
                taskList.clear();

                Tasks.saveTasks(tasks);
            }
        };

        addButton.addKeyListener(new KeyAdapter() {
            @Override
			public void keyReleased(KeyEvent e) {
                if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
                    saveAction.actionPerformed(null);
                    frame.dispose();
                }
            }
        });


        frame.addWindowListener(new WindowAdapter() {
            @Override
			public void windowClosing(WindowEvent windowEvent) {
                saveAction.actionPerformed(null);
            }
        });

        taskField.addKeyListener(new KeyAdapter() {
            @Override
			public void keyPressed(KeyEvent e) {
                if (e.getKeyChar() == KeyEvent.VK_ENTER) {
                    addAction.actionPerformed(null);
                }
            }
        });


        GraphicUtils.centerWindowOnComponent(frame, SparkManager.getMainWindow());
        frame.setVisible(true);
    }
    
    /**
     * Updates the GUI of Tasks
     */
    public static void updateTaskUI(Tasks tasks) {
    	panel_events.removeAll();
    	taskList.clear();
    	
        for (Task task : tasks.getTasks()) {
            final TaskUI taskUI = new TaskUI(task);
            if ( !SHOW_ALL_TASKS ) {
                taskUI.setVisible(!taskUI.isSelected());
            }
            panel_events.add(taskUI);
            taskList.add(taskUI);
        }
        
        panel_events.invalidate();
        panel_events.validate();
        panel_events.repaint();
        mainPanel.invalidate();
        mainPanel.validate();
        mainPanel.repaint();
        frame.invalidate();
        frame.validate();
        frame.repaint();
    }

    /**
     * Retrieve private notes from server.
     */
    private void retrieveNotes() {
        final SwingWorker notesWorker = new SwingWorker() {
            @Override
			public Object construct() {
                return PrivateNotes.getPrivateNotes();
            }

            @Override
			public void finished() {
                final PrivateNotes privateNotes = (PrivateNotes)get();
                showPrivateNotes(privateNotes);
            }
        };

        notesWorker.start();
    }

    private void showPrivateNotes(final PrivateNotes privateNotes) {
        String text = privateNotes.getNotes();

        final JLabel titleLabel = new JLabel(Res.getString("button.view.notes"));
        titleLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY));
        titleLabel.setFont(new Font("Dialog", Font.BOLD, 13));
        titleLabel.setHorizontalAlignment(JLabel.CENTER);

        final JTextPane pane = new JTextPane();
        pane.setFont(new Font("Dialog", Font.PLAIN, 12));

        pane.setOpaque(false);

        final JScrollPane scrollPane = new JScrollPane(pane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setOpaque(false);
        scrollPane.getViewport().setOpaque(false);

        pane.setText(text);
        final RolloverButton button = new RolloverButton(Res.getString("save"), null);
        final RolloverButton cancelButton = new RolloverButton(Res.getString("cancel"), null);
        ResourceUtils.resButton(button, Res.getString("button.save"));
        ResourceUtils.resButton(cancelButton, Res.getString("button.cancel"));

        final JFrame frame = new JFrame(Res.getString("title.notes"));


        final JPanel mainPanel = new JPanel();

        pane.addKeyListener(new KeyAdapter() {
            @Override
			public void keyReleased(KeyEvent e) {
                if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
                    frame.dispose();

                    // Save it.
                    String text = pane.getText();
                    privateNotes.setNotes(text);
                    PrivateNotes.savePrivateNotes(privateNotes);
                }
            }
        });

        mainPanel.setBackground(Color.white);
        mainPanel.setLayout(new GridBagLayout());
        frame.setIconImage(SparkManager.getMainWindow().getIconImage());
        frame.getContentPane().add(mainPanel);

        //   mainPanel.add(titleLabel, new GridBagConstraints(0, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));

        mainPanel.add(scrollPane, new GridBagConstraints(0, 1, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
        mainPanel.add(button, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
        mainPanel.add(cancelButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));

        frame.pack();
        frame.setSize(400, 400);

        GraphicUtils.centerWindowOnComponent(frame, SparkManager.getMainWindow());
        frame.setVisible(true);
        pane.setCaretPosition(0);

        button.addActionListener( actionEvent -> {
            frame.dispose();
            // Save it.
            String text1 = pane.getText();
            privateNotes.setNotes( text1 );
            PrivateNotes.savePrivateNotes(privateNotes);
        } );

        cancelButton.addActionListener( actionEvent -> frame.dispose() );
    }

    @Override
	public void shutdown() {
    }

    @Override
	public boolean canShutDown() {
        return true;
    }

    @Override
	public void uninstall() {
    }
    
    public static List<TaskUI> getTaskList() {
        return taskList;
    }

    /**
     * Delete task
     */
    public static void deleteTask(Task deletedTask) {
        List<TaskUI> taskList = getTaskList();
        // save Tasks
        Tasks tasks = new Tasks();
        for (TaskUI ui : taskList) {
            Task nTask = ui.getTask();
            if (nTask != deletedTask) {
                tasks.addTask(nTask);
            }
        }
        // update GUI
        updateTaskUI(tasks);
    }

}
