package transformation.associationtags;

import transformation.associationtags.buttonlisteners.*;

import com.nomagic.magicdraw.core.Application;
import com.nomagic.magicdraw.core.Project;
import com.nomagic.magicdraw.uml.symbols.DiagramPresentationElement;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Comment;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Diagram;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class AssociationTagWindow {
	
	List<String> protectedActions;
	List<String> roles;
	Project project = Application.getInstance().getProject();
	DiagramPresentationElement diagramPE = project.getActiveDiagram();
	DiagramExtension diagramExtension = new DiagramExtension(diagramPE);
	Diagram diagram = diagramPE.getDiagram();
	List<AssociationTag> tags = new ArrayList<AssociationTag>();
	List<JCheckBox> checkBoxes = new ArrayList<JCheckBox>();
	List<String> resources = new ArrayList<String>();
	Map<String, List<String>> partitionActionsMap;
	
	/**
	 * Constructor that finds the comment where the association tags are stored 
	 * and transforms the information into suitable form for manipulation  
	 */
	public AssociationTagWindow() {

		this.protectedActions = this.diagramExtension.getProtectedActionList();
		this.roles = this.diagramExtension.getRoleList();
		this.partitionActionsMap = this.diagramExtension.getPartitionActionsMap();
		
		// Finds the comment
		Comment comment = diagramExtension.getTagComment();
		String commentStr = "";
		if (comment != null) {
			commentStr = comment.getBody();
		}
		if (commentStr.length() > 2) {
			// Each line contains information about one association tag triplet
			String[] associationTagsStr = commentStr.split("\n");
			for (String tagStr : associationTagsStr) {
				if (tagStr.length() != 0) {
					if (tagStr.substring(0, 2).equals("::") == false) {
						// Creates an instance of the AssociationTag class, based on the information found on each line
						AssociationTag newTag = new AssociationTag();
						newTag.extractSelfFromStr(tagStr);
						/*String[] tagValues = tagStr.split(",");
						AssociationTag newTag = new AssociationTag(tagValues[0], tagValues[1], tagValues[2]);*/
						tags.add(newTag);
					}
					// The line which begins with "::" contains the names of protected resources
					else {
						for (String resource : tagStr.substring(2).split(",")) {
							resources.add(resource);
						}
					}
				}
			}
		}
		
	}
	

	/**
	 * Opens the window for displaying existing association tags
	 */
	public void showTags() {
		
		JFrame frame = new JFrame();
		frame.setTitle("Association tags");
		frame.setLayout(new BorderLayout());
		
		// The uppermost panel features the names of all swimlanes so that the user could choose,
		// which ones are protected resources
		JPanel resourcePanel = new JPanel();
		resourcePanel.setLayout(new BoxLayout(resourcePanel, BoxLayout.Y_AXIS));
		resourcePanel.add(new JLabel("Please tick the protected resources:"));
		if (checkBoxes.isEmpty()) {
			for (String swimlaneName : roles) {
				JCheckBox checkBox = new JCheckBox(swimlaneName);
				checkBox.addActionListener(new ResourceListener(this.partitionActionsMap, tags));
				// The names of protected resources that were found in the comment are pre-ticked
				if (resources.contains(swimlaneName)) {
					checkBox.setSelected(true);
				}
				checkBoxes.add(checkBox);
				resourcePanel.add(checkBox);
			}
		}
		else {
			for (JCheckBox checkBox : checkBoxes) {
				resourcePanel.add(checkBox);
			}
		}
		frame.add(resourcePanel, BorderLayout.NORTH);
		
		// The middle panel shows all association tags and buttons for editing/deleting them
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
		JScrollPane scrollPane = new JScrollPane(mainPanel);
		frame.add(scrollPane, BorderLayout.CENTER);
		if (tags.size() == 0) {
			mainPanel.add(new JLabel("No tags present, click \"Add\" to create some"));
		}
		
		for (AssociationTag tag : tags) {
			
			JPanel tagPanel = new JPanel();
			tagPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
			String tagStr = tag.toString();
			JTextArea textArea = new JTextArea(tagStr);
			textArea.setEditable(false);
			textArea.setSize(400, 95);
			tagPanel.add(textArea);
			tagPanel.setSize(400, 95);
			mainPanel.add(tagPanel);
			
			JPanel buttonPanel = new JPanel();
			buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
			
			JButton deleteButton = new JButton("Delete");
			deleteButton.addActionListener(new DeleteButtonListener(tags, tag, tagPanel, buttonPanel, roles));
			
			JButton editButton = new JButton("Edit");
			editButton.addActionListener(new EditButtonListener(frame, tag, tags, this));
			
			buttonPanel.add(deleteButton);
			buttonPanel.add(editButton);
			buttonPanel.setSize(400, 20);
			mainPanel.add(buttonPanel);		
		}
		
		// The bottom panel features the "OK" and "Add" buttons
		JPanel bottomPanel = new JPanel();
		bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		
		JButton okButton = new JButton("OK");
		okButton.addActionListener(new QuitListener(diagramExtension.getTagComment(), this.tags, frame, 
				this.diagramExtension, checkBoxes));
		bottomPanel.add(okButton);
		
		JButton addButton = new JButton("Add");
		addButton.addActionListener(new AddListener(this, frame));
		bottomPanel.add(addButton);
		
		frame.add(bottomPanel, BorderLayout.SOUTH);
		
		// The size of the frame is generated
		int x = tags.size() + 1;
		int y = roles.size();
		
		if (x > 5) {
			frame.setSize(400, 600 + y*20);
		}
		else {
			frame.setSize(400, 120*x + y*20 + 40);
		}
		
		mainPanel.setSize(frame.getSize());
		
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}
	
	/**
	 * The form for adding new association tags
	 */
	public void addTag() {

		// Two lists of protected actions (tags {protected = ...} and {right = ...}, the values of which are linked
		JComboBox actionList = new JComboBox(protectedActions.toArray());
		JComboBox actionList2 = new JComboBox(protectedActions.toArray());
		actionList.addActionListener(new MenuListener(actionList2));
		actionList2.addActionListener(new MenuListener(actionList));
		
		// Two lists of roles (tags {role = ...} and {right = ...}, the values of which are linked
		JComboBox roleList = new JComboBox(roles.toArray());
		JComboBox roleList2 = new JComboBox(roles.toArray());
		roleList.addActionListener(new MenuListener(roleList2));
		roleList2.addActionListener(new MenuListener(roleList));
		
		JFrame frame = new JFrame("Add association tag");
		frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
		
		JPanel upperPanel = new JPanel();
		upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
		JScrollPane scrollPane = new JScrollPane(upperPanel);
		
		JPanel labelPanel = new JPanel();
		JPanel inputPanel = new JPanel();
		
		labelPanel.setLayout(new GridLayout(3,1));
		inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
		
		JPanel protectedPanel = new JPanel();
		protectedPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
		JLabel label1 = new JLabel("protected = ");
		labelPanel.add(label1);
		protectedPanel.add(actionList);
		inputPanel.add(protectedPanel);
		
		JPanel rolePanel = new JPanel();
		rolePanel.setLayout(new FlowLayout(FlowLayout.LEFT));
		JLabel label2 = new JLabel("role = ");
		JTextField roleUser = new JTextField(10);
		labelPanel.add(label2);
		rolePanel.add(roleUser);
		rolePanel.add(roleList);
		inputPanel.add(rolePanel);
		
		JPanel rightPanel = new JPanel();
		rightPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
		JLabel label3 = new JLabel("right = ");
		labelPanel.add(label3);
		rightPanel.add(roleList2);
		rightPanel.add(actionList2);
		inputPanel.add(rightPanel);
		roleList2.setSelectedIndex(roleList.getSelectedIndex());
		actionList2.setSelectedIndex(actionList.getSelectedIndex());
		upperPanel.add(labelPanel);
		upperPanel.add(inputPanel);
		frame.add(scrollPane);
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new FlowLayout());
		
		// "OK" validates the information and adds the association tag and takes the user back to the display window
		JButton okButton = new JButton("OK");
		okButton.addActionListener(new OKButtonListener(
				actionList, roleUser, roleList, 
				diagramExtension, this, tags,
				checkBoxes, partitionActionsMap));
		
		// "Clear" restores the default values
		JButton clearButton = new JButton("Clear");
		clearButton.addActionListener(new ClearButtonListener(
				actionList, roleUser, roleList, roleList2, actionList2));
		
		// "Cancel" takes the user back to the display window without adding a new association tag
		JButton cancelButton = new JButton("Cancel");
		cancelButton.addActionListener(new CancelButtonListener(this));
		
		buttonPanel.add(okButton);
		buttonPanel.add(clearButton);
		buttonPanel.add(cancelButton);
		frame.add(buttonPanel);
		
		frame.setSize(470, 190);
		frame.setResizable(false);
		frame.setLocation(500, 500);
		frame.setVisible(true);
		
	}
	
	/**
	 * The form for editing an existing tag
	 * 
	 * @param action	Name of the current protected action
	 * @param user		Name of the current user
	 * @param role		Name of the current role
	 * @param index		Index of the association tag
	 */
	public void editTag(String action, String user, String role, int index) {

		// Two lists of protected actions (tags {protected = ...} and {right = ...}, the values of which are linked
		JComboBox actionList = new JComboBox(protectedActions.toArray());
		JComboBox actionList2 = new JComboBox(protectedActions.toArray());
		actionList.addActionListener(new MenuListener(actionList2));
		actionList2.addActionListener(new MenuListener(actionList));
		
		// Two lists of roles (tags {role = ...} and {right = ...}, the values of which are linked
		JComboBox roleList = new JComboBox(roles.toArray());
		JComboBox roleList2 = new JComboBox(roles.toArray());
		roleList.addActionListener(new MenuListener(roleList2));
		roleList2.addActionListener(new MenuListener(roleList));
		
		JFrame frame = new JFrame("Edit association tag");
		frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
		
		JPanel upperPanel = new JPanel();
		upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
		JScrollPane scrollPane = new JScrollPane(upperPanel);
		
		JPanel labelPanel = new JPanel();
		JPanel inputPanel = new JPanel();
		
		labelPanel.setLayout(new GridLayout(3,1));
		inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
		
		JPanel protectedPanel = new JPanel();
		protectedPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
		JLabel label1 = new JLabel("protected = ");
		labelPanel.add(label1);
		protectedPanel.add(actionList);
		inputPanel.add(protectedPanel);
		actionList.setSelectedIndex(protectedActions.indexOf(action));
				
		JPanel rolePanel = new JPanel();
		rolePanel.setLayout(new FlowLayout(FlowLayout.LEFT));
		JLabel label2 = new JLabel("role = ");
		JTextField roleUser = new JTextField(10);
		labelPanel.add(label2);
		rolePanel.add(roleUser);
		rolePanel.add(roleList);
		inputPanel.add(rolePanel);
		roleUser.setText(user);
		roleList.setSelectedIndex(roles.indexOf(role));
		
		JPanel rightPanel = new JPanel();
		rightPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
		JLabel label3 = new JLabel("right = ");
		labelPanel.add(label3);
		rightPanel.add(roleList2);
		rightPanel.add(actionList2);
		inputPanel.add(rightPanel);
		
		roleList2.setSelectedIndex(roleList.getSelectedIndex());
		actionList2.setSelectedIndex(actionList.getSelectedIndex());
		
		upperPanel.add(labelPanel);
		upperPanel.add(inputPanel);
		frame.add(scrollPane);
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new FlowLayout());
		
		// "OK" validates the information, deletes the old association tag,
		// adds a new one in its place and takes the user back to the display window
		JButton okButton = new JButton("OK");
		okButton.addActionListener(new EditOKButtonListener(actionList, roleUser, roleList,
				diagramExtension, this, tags, index));
		
		// "Cancel" takes the user back to the display window without changing the association tag
		JButton cancelButton = new JButton("Cancel");
		cancelButton.addActionListener(new EditCancelButtonListener(this));
		
		buttonPanel.add(okButton);
		buttonPanel.add(cancelButton);
		frame.add(buttonPanel);
		
		frame.setSize(470, 190);
		frame.setResizable(false);
		frame.setLocation(500, 500);
		frame.setVisible(true);
		
		
	}
}
