package open.dolphin.client.labotestimporter;

import java.util.Arrays;
import java.util.concurrent.Callable;
import open.dolphin.client.Dolphin.MenuMediator;

import open.dolphin.project.GlobalConstants;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;

import open.dolphin.infomodel.LaboImportSummary;
import open.dolphin.infomodel.PatientModel;
import open.dolphin.infomodel.PatientVisitModel;
import open.dolphin.project.GlobalVariables;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import java.util.List;
import java.util.prefs.Preferences;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import open.dolphin.client.GUIConst;
import open.dolphin.client.IMainComponent;
import open.dolphin.client.IMainWindow;
import open.dolphin.client.ObjectListTable;
import open.dolphin.client.SeparatorPanel;
import open.dolphin.table.ObjectReflectTableModel;
import open.dolphin.utils.FileOpenDialog;
import open.dolphin.helper.IMainCommandAccepter;

/**
 * 検査入力　MEMO:画面　リスナー
 * @author
 */
public class LaboTestImporter extends javax.swing.JPanel implements IMainComponent, PropertyChangeListener, IMainCommandAccepter {

    private String name;
    private String icon;
    private IMainWindow context;
    // private JPanel ui;
    private static final String NAME = "ラボレシーバ";
    // 選択されている患者情報
    private LaboImportSummary selectedLabo;
    private int number = 100000;
    // GUI コンポーネント
    private ObjectListTable laboListTable;
    private JProgressBar usp;
    private JLabel countLabel;
    private JLabel dateLabel;

    /** 
     * Creates new form LaboTestImporter
     */
    public LaboTestImporter() {
        initComponents();
        this.name = NAME;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, Short.MAX_VALUE));
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, Short.MAX_VALUE));
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Variables declaration - do not modify//GEN-BEGIN:variables
     * End of variables declaration//GEN-END:variables
     */
    @Override
    public void start() {
        initCustomComponents();
        connect();
        enter();
    }

    /**
     *
     */
    @Override
    public void enter() {
        controlMenu();
    }

    /**
     *
     */
    @Override
    public void stop() {
    }

    /**
     *
     * @return
     */
    public LaboImportSummary getSelectedLabo() {
        return selectedLabo;
    }

    /**
     *
     * @param command
     * @return
     */
    @Override
    public boolean dispatchMainCommand(open.dolphin.helper.IMainCommandAccepter.MainCommand command) {
        return false;
    }

    /**
     *
     * @return
     */
    @Override
    public String getName() {
        return name;
    }

    /**
     *
     * @param name
     */
    @Override
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return
     */
    @Override
    public String getIcon() {
        return icon;
    }

    /**
     *
     * @param icon
     */
    @Override
    public void setIcon(String icon) {
        this.icon = icon;
    }

    /**
     *
     * @return
     */
    @Override
    public IMainWindow getContext() {
        return context;
    }

    /**
     *
     * @param context
     */
    @Override
    public void setContext(IMainWindow context) {
        this.context = context;
    }

    //  @Override
    //  public JPanel getPanel() {
    //   }
    // @Override
    //  public void setPanel(JPanel ui) {
    //  this.ui = ui;
    //  }
    /**
     *
     * @return
     */
    @Override
    public Callable<Boolean> getStartingTask() {
        return null;
    }

    /**
     *
     * @return
     */
    @Override
    public Callable<Boolean> getStoppingTask() {
        return null;
    }

    /**
     *
     * @param midiator
     */
    @Override
    public void setMenu(MenuMediator midiator) {
    }

    /**
     * 受付リストのコンテキストメニュークラス。
     */
    class ContextListener extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            mabeShowPopup(e);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            mabeShowPopup(e);
        }

        public void mabeShowPopup(MouseEvent e) {
            if (e.isPopupTrigger()) {
                final JPopupMenu contextMenu = new JPopupMenu();

                int row = laboListTable.rowAtPoint(e.getPoint());
                //     Object obj = laboListTable.getTableModel().getObject(row);
                Object obj = ((ObjectReflectTableModel<Object>) laboListTable.getModel()).getObject(row);
                int selected = laboListTable.getSelectedRow();

                if (row == selected && obj != null) {
                    String pop1 = "カルテを開く"; //GlobalVariables.getString("waitingList.popup.openKarte");
                    //  contextMenu.add(new JMenuItem(new ReflectAction(pop1, LaboTestImporter.this, "openKarte")));
                    contextMenu.add(new JMenuItem(
                            new AbstractAction(pop1) {

                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    LaboTestImporter.this.openKarte();
                                }
                            }));
                }
                contextMenu.show(e.getComponent(), e.getX(), e.getY());
            }
        }
    }

    /**
     *
     * @param selectedLabo
     */
    public void setSelectedLabo(LaboImportSummary selectedLabo) {
        this.selectedLabo = selectedLabo;
        controlMenu();
    }

    /**
     *
     * @return
     */
    private boolean openKarte() {
        final Preferences pref = Preferences.userNodeForPackage(this.getClass());
        boolean showReceiptMessage = pref.getBoolean("showReceiptMessage", true);
        showReceiptMessage = true;
        if (showReceiptMessage) {
            JLabel msg1 = new JLabel("受付リストからオープンしないと診療データをレセコンに");
            JLabel msg2 = new JLabel("送信することができません。続けますか?");
            final JCheckBox cb = new JCheckBox("今後このメッセージを表示しない");
            cb.setFont(new Font("Dialog", Font.PLAIN, 10));
            cb.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    pref.putBoolean("showReceiptMessage", !cb.isSelected());
                }
            });
            JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 3));
            p1.add(msg1);
            JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 3));
            p2.add(msg2);
            JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 3));
            p3.add(cb);
            JPanel box = new JPanel();
            box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
            box.add(p1);
            box.add(p2);
            box.add(p3);
            box.setBorder(BorderFactory.createEmptyBorder(0, 0, 11, 11));

            int option = JOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(this),
                    new Object[]{box},
                    GlobalConstants.getFrameTitle(getName()),
                    JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE,
                    GlobalConstants.getImageIcon("about_32.gif"));

            if (option != JOptionPane.YES_OPTION) {
                return true;
            }
        }

        PatientModel patient = selectedLabo.getPatient();
        PatientVisitModel pvt = new PatientVisitModel();
        pvt.setNumber(number);
        number++;
        pvt.setPatient(patient);

        // 受け付けを通していないので診療科はユーザ登録してあるものを使用する
        StringBuilder sb = new StringBuilder();
        sb.append(GlobalVariables.getUserModel().getDepartmentModel().getDepartmentDesc());
        sb.append(",");
        sb.append(GlobalVariables.getUserModel().getDepartmentModel().getDepartment());
        // Doctor name, id, JMARI code
        pvt.setDepartment(sb.toString());

        // カルテコンテナを生成する
        getContext().openKarte(pvt, "");
        return true;
    }

    /**
     *
     * @return
     */
    public ObjectListTable getLaboListTable() {
        return laboListTable;
    }

    /**
     *
     * @return
     */
    public JProgressBar getProgressBar() {
        return usp;
    }

    /**
     * 検索結果件数を設定しステータスパネルへ表示する。
     */
    public void updateCount() {
        //   int count = laboListTable.getTableModel().getObjectCount();
        int count = ((ObjectReflectTableModel<Object>) laboListTable.getModel()).getObjectCount();
        String text = "登録件数:"; //GlobalVariables.getString("laboTestImport.count.text");
        text += String.valueOf(count);
        countLabel.setText(text);
    }

    /**
     * メニューを制御する
     */
    private void controlMenu() {
        PatientModel pvt = getSelectedLabo() != null
                ? getSelectedLabo().getPatient()
                : null;

        boolean enabled = canOpen(pvt);
        getContext().enabledAction(GUIConst.ACTION_OPEN_KARTE, enabled);
    }

    /**
     * カルテを開くことが可能かどうかを返す。
     * @return 開くことが可能な時 true
     */
    private boolean canOpen(PatientModel patient) {
        if (patient == null) {
            return false;
        }

        if (isKarteOpened(patient)) {
            return false;
        }

        return true;
    }

    /**
     * カルテがオープンされているかどうかを返す。
     * @return オープンされている時 true
     */
    private boolean isKarteOpened(PatientModel patient) {
        return context.isKarteOpened(patient.getId());
    }

    /**
     * GUI コンポーネントを初期化する。
     */
    private void initCustomComponents() {
        JButton iconButton = new JButton(GlobalConstants.getImageIcon("impt_24.gif"));
        //JLabel iconLabel = new JLabel(GlobalVariables.getImageIcon("impt_24.gif"));
        JLabel instLabel = new JLabel("検査結果ファイル(MML形式)を下のテーブルに Drag & Drop してください。");
        instLabel.setFont(new Font("Dialog", Font.PLAIN, 10)); //GlobalVariables.getInt("waitingList.state.font.size")));
        final JPanel importPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        importPanel.add(iconButton);
        importPanel.add(instLabel);

        iconButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                iconButtonClicked(importPanel);
            }
        });
        // ラボテストテーブルを生成する
        String[] columnNames = {"患者氏名", "性別", "テスト/検体名", "検体採取日", "報告日", "ステータス", "ラボ名"}; //GlobalVariables.getStringArray("labotestImport.columnNames");
        int startNumRows = 30; //GlobalVariables.getInt("labotestImport.startNumRows");
        String[] methodNames = {"getPatientName", "getPatientGender", "getSetName", "getSampleTime", "getReportTime", "getReportStatus", "getLaboratoryCenter", ""}; //GlobalVariables.getStringArray("labotestImport.methodNames");
        Class[] classes = GlobalConstants.getClassArray("labotestImport.classNames");
        int[] columnWidth = GlobalConstants.getIntArray("labotestImport.columnWidth");
        int rowHeight = 18; //GlobalVariables.getInt("labotestImport.rowHeight");
        laboListTable = new ObjectListTable(columnNames, startNumRows, methodNames, classes);
        laboListTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        laboListTable.setColumnWidth(columnWidth);
        laboListTable.setRowHeight(rowHeight);
        JScrollPane scroller = laboListTable.getScroller();

        // TransferHandlerを設定する
        //      JTable table = laboListTable;
        laboListTable.setTransferHandler(new LaboTestFileTransferHandler(this));

        // Status パネルを生成する
        usp = new JProgressBar();
        Font font = new Font("Dialog", Font.PLAIN, 10); //GlobalVariables.getInt("waitingList.state.font.size"));
        countLabel = new JLabel("");
        dateLabel = new JLabel("");
        countLabel.setFont(font);
        dateLabel.setFont(font);
        countLabel.setHorizontalAlignment(SwingConstants.CENTER);
        dateLabel.setHorizontalAlignment(SwingConstants.CENTER);
        JPanel statusP = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
        statusP.add(usp);
        statusP.add(countLabel);
        statusP.add(new SeparatorPanel());
        statusP.add(dateLabel);

        // カウント値０を設定する
        updateCount();

        // 日付を設定する
        String formatStr = "yyyy-MM-dd (EE)"; //GlobalVariables.getString("waitingList.state.dateFormat");
        SimpleDateFormat sdf = new SimpleDateFormat(formatStr); // 2006-11-20(水)
        dateLabel.setText(sdf.format(new Date()));

        // 全体をレイアウトする
        //   setPanel(new JPanel());
        //     JPanel myPanel = getPanel();
        setLayout(new BorderLayout(0, 11));
        add(importPanel, BorderLayout.NORTH);
        add(scroller, BorderLayout.CENTER);
        add(statusP, BorderLayout.SOUTH);
        setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11));
    }

    /**
     * コンポーンントにリスナを登録し接続する。
     */
    private void connect() {
        // ダブルクリックでカルテオープンする
        laboListTable.addPropertyChangeListener(ObjectListTable.DOUBLE_CLICKED_OBJECT, this);
        // コンテキストメニューリスナを設定する
        laboListTable.addMouseListener(new ContextListener());

        // 行選択
        PropertyChangeListener pls = new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent e) {
                if (e.getPropertyName().equals(ObjectListTable.SELECTED_OBJECT)) {
                    Object[] obj = (Object[]) e.getNewValue();
                    // 情報をリフレッシュするため null かどうかに関係なくセットし通知する必要がある
                    LaboImportSummary value = (obj != null && obj.length > 0) ? (LaboImportSummary) obj[0] : null;
                    setSelectedLabo(value);
                }
            }
        };
        laboListTable.addPropertyChangeListener(ObjectListTable.SELECTED_OBJECT, pls);
    }

    /**
     * ダブルクリックされた患者のカルテを開く。
     * @param e 
     */
    @Override
    public void propertyChange(PropertyChangeEvent e) {
        String prop = e.getPropertyName();
        if (prop.equals(ObjectListTable.DOUBLE_CLICKED_OBJECT)) {
            LaboImportSummary value = (LaboImportSummary) e.getNewValue();
            if (value != null) {
                setSelectedLabo(value);
                if (canOpen(value.getPatient())) {
                    openKarte();
                }
            }
        }
    }

    /**
     * ボタンをクリックしたときのアクション
     *
     * ファイルダイアログから選択したファイルをパースする。
     *
     * @param parent
     */
    private void iconButtonClicked(Component parent) {
        FileOpenDialog chooser = new FileOpenDialog(parent, "", FileOpenDialog.LOAD, "");
        chooser.setFileSelectionMode(FileOpenDialog.FILES_ONLY);
        chooser.setMultiSelectionEnabled(true);
        FileFilter filter = new FileNameExtensionFilter("スタンプファイル", "xml", "txt");
        chooser.addChoosableFileFilter(filter);
        int result = chooser.open();
        if (result == FileOpenDialog.APPROVE_OPTION) {
            File[] files = chooser.getSelectedFiles();
            List<File> fileList = new ArrayList<File>();
            fileList.addAll(Arrays.asList(files));
            LaboTestFileTransferHandler handler = new LaboTestFileTransferHandler(this);
            handler.addFiles(fileList);
        }
    }
}
