import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.text.DefaultEditorKit;

class Gui extends JFrame implements ActionListener, MouseListener {
	private static final long serialVersionUID = 1L;

	JTextArea taGL, taIS, taNum, taBL, tafGL, tafIS, tafBL;
	static JTextArea taRE;
	JButton bPlanning, bView, bFileLoad, bSave, bOP;
	JLabel lIS, lG, lNum, lRE, lFN, lBL, lfIS, lfG, lfBL, lsFN, loFN;
	JRadioButton rbFileLoad, rbInput;
	JPanel pINP, pLOAD;
	String gft, ift, tmpBlock, initialState, goal;
	pGraphics grap = null;// グラフィック
	JPopupMenu popup;
	JFrame f;

	Gui() throws IOException {
		myframe();
	}

	void myframe() {

		f = new JFrame("Planning");
		pINP = new JPanel();
		pLOAD = new JPanel();
		JPanel pRE = new JPanel();

		// パネルに枠を追加
		BevelBorder border = new BevelBorder(BevelBorder.RAISED);
		pINP.setBorder(border);
		pLOAD.setBorder(border);
		pRE.setBorder(border);

		// ボタン
		bPlanning = new JButton("Planning");
		bView = new JButton("View");
		bFileLoad = new JButton("Load");
		bSave = new JButton("Save");
		bOP = new JButton("Operator File");

		// テキストエリア
		taGL = new JTextArea("B on A");
		taIS = new JTextArea("ontable B\nA on B\nclear A\nhandEmpty");
		taNum = new JTextArea("Number??");
		taRE = new JTextArea("");
		taBL = new JTextArea(
				"block A red triangle\nblock B blue square\nblock C yellow square\nblock D green triangle");
		tafGL = new JTextArea("");
		tafIS = new JTextArea("");
		tafBL = new JTextArea("");

		// ラベル
		EtchedBorder border2 = new EtchedBorder(EtchedBorder.RAISED,
				Color.white, Color.black);
		lIS = new JLabel("InitialState");
		lG = new JLabel("Goal");
		lNum = new JLabel("Number");
		lRE = new JLabel("Result");
		lFN = new JLabel("SELECTED FILE NAME");
		lFN.setBorder(border2);
		lBL = new JLabel("Block");
		lfIS = new JLabel("InitialState");
		lfG = new JLabel("Goal");
		lfBL = new JLabel("Block");
		lsFN = new JLabel("SELECTED FILE NAME");
		lsFN.setBorder(border2);
		loFN = new JLabel("operator.txt");
		loFN.setBorder(border2);

		// ラベル初期設定
		lfIS.setForeground(Color.lightGray);
		lfG.setForeground(Color.lightGray);
		lfBL.setForeground(Color.lightGray);
		lFN.setForeground(Color.lightGray);
		lFN.setOpaque(true);
		lsFN.setOpaque(true);
		loFN.setOpaque(true);
		lFN.setBackground(Color.white);
		lsFN.setBackground(Color.white);
		loFN.setBackground(Color.white);
		lFN.setHorizontalAlignment(JLabel.CENTER);
		lsFN.setHorizontalAlignment(JLabel.CENTER);
		loFN.setHorizontalAlignment(JLabel.CENTER);

		// ラジオボタン初期設定
		rbFileLoad = new JRadioButton("FileLoad", false);
		rbInput = new JRadioButton("Input", true);
		rbFileLoad.addActionListener(this);
		rbInput.addActionListener(this);
		ButtonGroup group = new ButtonGroup();
		group.add(rbFileLoad);
		group.add(rbInput);
		rbFileLoad.setOpaque(false);
		rbInput.setOpaque(false);

		bPlanning.addActionListener(this);
		bView.addActionListener(this);
		bFileLoad.addActionListener(this);
		bFileLoad.setForeground(Color.lightGray);
		bFileLoad.setEnabled(false);
		bSave.addActionListener(this);
		bOP.addActionListener(this);

		// グラフィックス用クラスの呼び出し
		grap = new pGraphics();

		// テキストエリア設定
		taGL.setWrapStyleWord(true);
		taGL.setLineWrap(true);
		JScrollPane spGL = new JScrollPane(taGL);
		getContentPane().add(spGL);

		taIS.setWrapStyleWord(true);
		taIS.setLineWrap(true);
		JScrollPane spIS = new JScrollPane(taIS);
		getContentPane().add(spIS);

		taRE.setWrapStyleWord(true);
		taRE.setLineWrap(true);
		JScrollPane spRE = new JScrollPane(taRE);
		getContentPane().add(spRE);
		taRE.setEditable(false);

		taBL.setWrapStyleWord(true);
		taBL.setLineWrap(true);
		JScrollPane spBL = new JScrollPane(taBL);
		getContentPane().add(spBL);

		tafGL.setWrapStyleWord(true);
		tafGL.setLineWrap(true);
		JScrollPane spfGL = new JScrollPane(tafGL);
		getContentPane().add(spfGL);
		tafGL.setEditable(false);

		tafIS.setWrapStyleWord(true);
		tafIS.setLineWrap(true);
		JScrollPane spfIS = new JScrollPane(tafIS);
		getContentPane().add(spfIS);
		tafIS.setEditable(false);

		tafBL.setWrapStyleWord(true);
		tafBL.setLineWrap(true);
		JScrollPane spfBL = new JScrollPane(tafBL);
		getContentPane().add(spfBL);
		tafBL.setEditable(false);

		// 入力部パネル設定
		pINP.add(rbInput);
		pINP.add(lIS);
		pINP.add(spIS);
		pINP.add(lG);
		pINP.add(spGL);
		pINP.add(lBL);
		pINP.add(spBL);
		pINP.add(bSave);
		pINP.add(lsFN);
		pINP.setLayout(null);

		rbInput.setBounds(5, 15, 100, 15);
		bSave.setBounds(15, 40, 220, 30);
		lsFN.setBounds(15, 75, 220, 20);
		lIS.setBounds(15, 100, 100, 30);
		spIS.setBounds(15, 130, 220, 100);
		lG.setBounds(15, 230, 100, 30);
		spGL.setBounds(15, 260, 220, 100);
		lBL.setBounds(15, 360, 100, 30);
		spBL.setBounds(15, 390, 220, 100);

		f.add(pINP);

		// ロード部パネル設定
		pLOAD.add(rbFileLoad);
		pLOAD.add(bFileLoad);
		pLOAD.add(lFN);
		pLOAD.add(lfIS);
		pLOAD.add(spfIS);
		pLOAD.add(lfG);
		pLOAD.add(spfGL);
		pLOAD.add(lfBL);
		pLOAD.add(spfBL);
		pLOAD.setLayout(null);
		pLOAD.setBackground(Color.white);

		rbFileLoad.setBounds(5, 15, 100, 15);
		bFileLoad.setBounds(15, 40, 220, 30);
		lFN.setBounds(15, 75, 220, 20);
		lfIS.setBounds(15, 100, 100, 30);
		spfIS.setBounds(15, 130, 220, 100);
		lfG.setBounds(15, 230, 100, 30);
		spfGL.setBounds(15, 260, 220, 100);
		lfBL.setBounds(15, 360, 100, 30);
		spfBL.setBounds(15, 390, 220, 100);

		f.add(pLOAD);

		// 結果表示部パネル設定
		pRE.add(bPlanning);
		pRE.add(bView);
		pRE.add(bOP);
		pRE.add(loFN);
		pRE.add(lRE);
		pRE.add(spRE);
		pRE.setLayout(null);

		bOP.setBounds(15, 15, 220, 30);
		loFN.setBounds(15, 50, 220, 20);
		bPlanning.setBounds(15, 85, 105, 30);
		bView.setBounds(130, 85, 105, 30);
		lRE.setBounds(15, 120, 100, 30);
		spRE.setBounds(15, 150, 220, 340);

		f.add(pRE);

		// フレーム設定
		f.setSize(750, 530);
		f.setVisible(true);
		f.setResizable(false);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		f.setLayout(null);
		pINP.setBounds(0, 0, 250, 510);
		pLOAD.setBounds(250, 0, 250, 510);
		pRE.setBounds(500, 0, 250, 510);

		// ポップアップメニュー用設定
		taIS.addMouseListener(this);
		taGL.addMouseListener(this);
		taBL.addMouseListener(this);
		tafIS.addMouseListener(this);
		tafGL.addMouseListener(this);
		tafBL.addMouseListener(this);
		taRE.addMouseListener(this);
	}

	// ポップアップメニュー表示用
	public void mouseReleased(MouseEvent e) {
		showPopup(e);
	}

	public void mousePressed(MouseEvent e) {
		showPopup(e);
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	private void showPopup(MouseEvent e) {
		if (e.isPopupTrigger()) {

			popup = new JPopupMenu();
			JComponent c = (JComponent) e.getComponent();
			ActionMap am = c.getActionMap();
			Action cut = am.get(DefaultEditorKit.cutAction);
			Action copy = am.get(DefaultEditorKit.copyAction);
			Action paste = am.get(DefaultEditorKit.pasteAction);

			JMenuItem cuMI = popup.add(cut);
			cuMI.setText("cut");
			JMenuItem cpMI = popup.add(copy);
			cpMI.setText("copy");
			popup.addSeparator();
			JMenuItem paMI = popup.add(paste);
			paMI.setText("paste");
			popup.show(e.getComponent(), e.getX(), e.getY());
		}
	}

	Planner myPlanner = new Planner();
	boolean viewd = false;

	// プランニングボタンが押された時の処理
	void start(int i) {
		String[] goals = null;
		String[] inits = null;

		if (i == 1) {// インプットの場合
			goals = (taGL.getText()).split("\n");
			inits = (taIS.getText()).split("\n");
		} else if (i == 2) {// ファイルロードの場合
			goals = (goal).split("\n");
			inits = (initialState).split("\n");
		}
		myPlanner.start(initListi(goals), initListi(inits));
		if (viewd)
			grap.initSolution(myPlanner);
		viewd = false;
	}

	// @Override
	public void actionPerformed(ActionEvent ae) {
		if (ae.getSource() == bPlanning) {// プランニング実行要求
			if (rbInput.isSelected()) {
				this.start(1);
			} else if (rbFileLoad.isSelected()) {
				if (goal != null) {
					this.start(2);
				} else {
					JLabel msg = new JLabel("ERROR：ファイル選択に問題があります。");
					JOptionPane.showMessageDialog(f, msg);
				}
			}
		} else if (ae.getSource() == bView) {// グラフィック表示要求
			viewd = true;
			if (rbInput.isSelected()) {
				String[] inits = (taIS.getText()).split("\n");
				BlockOp.list.clear();
				blockTrans(taBL.getText());
				// myPlanner.initBlock();
				grap.initDisp(inits);
			} else if (rbFileLoad.isSelected()) {
				if (goal != null) {
					String[] inits = (initialState).split("\n");
					BlockOp.list.clear();
					blockTrans(tmpBlock);
					grap.initDisp(inits);
				} else {
					JLabel msg = new JLabel("ERROR：ファイル選択に問題があります。");
					JOptionPane.showMessageDialog(f, msg);
				}
			}
		} else if (ae.getSource() == bFileLoad) {// ファイルロード要求
			JFileChooser filechooser = new JFileChooser(".");
			int selected = filechooser.showOpenDialog(this);
			if (selected == JFileChooser.APPROVE_OPTION) {
				File file = filechooser.getSelectedFile();
				lFN.setText(file.getName());
				txtFileLoad(file);
				tafIS.append(initialState);
				tafGL.append(goal);
				tafBL.append(tmpBlock);
			} else if (selected == JFileChooser.ERROR_OPTION) {
				JLabel msg = new JLabel("ERROR：ファイルを開くことができません");
				JOptionPane.showMessageDialog(f, msg);
			}
		} else if (ae.getSource() == bSave) {// ファイルセーブ要求
			JFileChooser filechooser = new JFileChooser();
			int selected = filechooser.showSaveDialog(this);
			if (selected == JFileChooser.APPROVE_OPTION) {
				File file = filechooser.getSelectedFile();
				lsFN.setText(file.getName());
				txtFileSave(file);
			} else if (selected == JFileChooser.ERROR_OPTION) {
				JLabel msg = new JLabel("ERROR：ファイルに書きこむことができません");
				JOptionPane.showMessageDialog(f, msg);
			}
		} else if (ae.getSource() == rbInput) {// ラジオボタンの選択が変更された際の動作
			if (rbInput.isSelected()) {
				changeRB(1);
			}
		} else if (ae.getSource() == rbFileLoad) {// 同
			if (rbFileLoad.isSelected()) {
				changeRB(2);
			}
		} else if (ae.getSource() == bOP) {// オペレータファイル選択
			JFileChooser filechooser = new JFileChooser();
			int selected = filechooser.showSaveDialog(this);
			if (selected == JFileChooser.APPROVE_OPTION) {
				File file = filechooser.getSelectedFile();
				loFN.setText(file.getName());
				/*
				 * 
				 * 
				 * 
				 * オペレータファイル読み込み file.getName()が選択されたファイル名
				 */
			} else if (selected == JFileChooser.ERROR_OPTION) {
				JLabel msg = new JLabel("ERROR：ファイルを開くことができません");
				JOptionPane.showMessageDialog(f, msg);
			}
		}
	}

	/**
	 * Gui用読み込みメソッド　 引数にゴール状態OR初期状態の配列 それをベクターにするだけです。
	 * 
	 */
	private ArrayList<String> initListi(String[] strs) {
		ArrayList<String> List = new ArrayList<String>();
		for (String i : strs) {
			List.add(i);
		}
		return List;
	}

	/**
	 * ファイルリード前チェック用
	 * 
	 */
	private static boolean checkBeforeReadfile(File file) {
		if (file.exists()) {
			if (file.isFile() && file.canRead()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * テキストファイルからゴール・初期状態・ブロックリストを抽出する
	 * 
	 */
	public void txtFileLoad(File file) {
		int i = 0;
		String tmpFileLine;
		tmpBlock = null;
		initialState = null;
		goal = null;

		try {
			if (checkBeforeReadfile(file)) {
				BufferedReader fileread = new BufferedReader(new FileReader(
						file));
				while ((tmpFileLine = fileread.readLine()) != null) {
					if (tmpFileLine.equals("[def]")) {
						i = 1;
					} else if (tmpFileLine.equals("[init]")) {
						i = 2;
					} else if (tmpFileLine.equals("[goal]")) {
						i = 3;
					}

					if (i == 1) {
						if (tmpBlock == null) {
							if (tmpFileLine.equals("[def]") != true)
								tmpBlock = tmpFileLine;
						} else
							tmpBlock = tmpBlock.concat("\n" + tmpFileLine);
					} else if (i == 2) {
						if (initialState == null) {
							if (tmpFileLine.equals("[init]") != true)
								initialState = tmpFileLine;
						} else
							initialState = initialState.concat("\n"
									+ tmpFileLine);
					} else if (i == 3) {
						if (goal == null) {
							if (tmpFileLine.equals("[goal]") != true)
								goal = tmpFileLine;
						} else
							goal = goal.concat("\n" + tmpFileLine);
					}
				}
				fileread.close();
			} else {
				JLabel msg = new JLabel("ERROR：ファイルを開くことができません");
				JOptionPane.showMessageDialog(f, msg);
			}
		} catch (FileNotFoundException err) {
			System.out.println(err);
		} catch (IOException err) {
			System.out.println(err);
		}
	}

	/**
	 * テキストファイルに初期状態、目標、ブロックを保存するメソッド
	 * 
	 */
	public void txtFileSave(File file) {
		try {
			Writer out = new OutputStreamWriter(new FileOutputStream(file),
					"utf-8");
			out.write("[def]\n");
			out.write(taBL.getText() + "\n\n");
			out.write("[init]\n");
			out.write(taIS.getText() + "\n\n");
			out.write("[goal]\n");
			out.write(taGL.getText() + "\n\n");
			out.close();
		} catch (IOException err) {
		}

	}

	/**
	 * ファイルから読み込んだブロックリストを使用可能な状態に処理
	 * 
	 */
	public void blockTrans(String blockList) {
		String[] block = (blockList).split("\n");
		int k = block.length;
		String[][] bls = new String[k][4];
		for (int a = 0; a < block.length; a++) {
			bls[a] = block[a].split(" ");
		}
		for (int a = 0; a < bls.length; a++) {
			BlockOp.addBlock(bls[a][1], bls[a][2], bls[a][3]);
		}
	}

	/**
	 * ラジオボタンの選択が変更されたとき、表示色とか変えるメソッド
	 * 
	 * @param i
	 */
	public void changeRB(int i) {
		if (i == 1) {
			lfIS.setForeground(Color.lightGray);
			lfG.setForeground(Color.lightGray);
			lfBL.setForeground(Color.lightGray);
			lFN.setForeground(Color.lightGray);
			bFileLoad.setEnabled(false);
			bFileLoad.setForeground(Color.lightGray);
			pLOAD.setBackground(Color.white);
			tafGL.setForeground(Color.lightGray);
			tafIS.setForeground(Color.lightGray);
			tafBL.setForeground(Color.lightGray);

			lIS.setForeground(Color.black);
			lG.setForeground(Color.black);
			lBL.setForeground(Color.black);
			lsFN.setForeground(Color.black);
			bSave.setEnabled(true);
			bSave.setForeground(Color.black);
			pINP.setBackground(null);
			taGL.setEditable(true);
			taIS.setEditable(true);
			taBL.setEditable(true);
			taGL.setForeground(Color.black);
			taIS.setForeground(Color.black);
			taBL.setForeground(Color.black);
		} else if (i == 2) {
			lfIS.setForeground(Color.black);
			lfG.setForeground(Color.black);
			lfBL.setForeground(Color.black);
			lFN.setForeground(Color.black);
			bFileLoad.setEnabled(true);
			bFileLoad.setForeground(Color.black);
			pLOAD.setBackground(null);
			tafGL.setForeground(Color.black);
			tafIS.setForeground(Color.black);
			tafBL.setForeground(Color.black);

			lIS.setForeground(Color.lightGray);
			lG.setForeground(Color.lightGray);
			lBL.setForeground(Color.lightGray);
			lsFN.setForeground(Color.lightGray);
			bSave.setEnabled(false);
			bSave.setForeground(Color.lightGray);
			pINP.setBackground(Color.white);
			taGL.setEditable(false);
			taIS.setEditable(false);
			taBL.setEditable(false);
			taGL.setForeground(Color.lightGray);
			taIS.setForeground(Color.lightGray);
			taBL.setForeground(Color.lightGray);
		}
	}
}