/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * PatientInfoDocumentPanel.java
 *
 * Created on 2010/03/08, 15:06:36
 */
package open.dolphin.plugin;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.util.ArrayList;
import java.util.Collection;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;

import open.dolphin.project.GlobalConstants;
import open.dolphin.client.ChartMediator;
import open.dolphin.client.GUIConst;
import open.dolphin.client.IChart;
import open.dolphin.client.IChartDocument;
import open.dolphin.client.IChartDocument.TYPE;
import open.dolphin.delegater.remote.RemotePatientDelegater;

import open.dolphin.infomodel.PVTHealthInsuranceModel;
import open.dolphin.infomodel.PVTPublicInsuranceItemModel;
import open.dolphin.infomodel.PatientModel;

import open.dolphin.project.GlobalSettings;
import open.dolphin.project.GlobalVariables;
import open.dolphin.table.OddEvenRowRenderer;
import open.dolphin.helper.IChartCommandAccepter;

/**
 *
 * @author oda
 */
public class PatientInfoDocumentPanel extends javax.swing.JPanel implements IChartDocument, IChartCommandAccepter {//, IMainCommandAccepter

    // Title
    /**
     *
     */
    public static final String TITLE = "患者情報";
    // 患者属性名
    private static final String[] PATIENT_ATTRS = {
        "患者 ID", "氏  名", "カナ", "ローマ字 *", "性  別", "生年月日", "国  籍 *", "婚姻状況 *", "郵便番号", "住  所", "電  話", "携帯電話 *", "電子メール *"
    };
    // Info アイコン
    private static final String INFO_BUTTON_IMAGE = "about_16.gif";
    private static final String INFO = "* の項目は編集が可能です";
    // カラム名
    private static final String[] COLUMN_NAMES = {"項   目", "値"};
    // 編集可能な行
    private static final int[] EDITABLE_ROWS = {3, 6, 7, 11, 12};
    // 保存アイコン
    private static final String SAVE_ICON = "save_16.gif";
    // 保存ボタン
    private JButton saveBtn;
    // テーブルモデル
    private PatientInfoTableModel pModel;
    // 属性表示テーブル
    private JTable pTable;
    // State Context
    private StateContext stateMgr;
    //元々はAbstractChartDocumentから継承
    private static final String[] CHART_MENUS = {
        GUIConst.ACTION_OPEN_KARTE, GUIConst.ACTION_SAVE, GUIConst.ACTION_DIRECTION, GUIConst.ACTION_DELETE, GUIConst.ACTION_PRINT, GUIConst.ACTION_MODIFY_KARTE,
        GUIConst.ACTION_ASCENDING, GUIConst.ACTION_DESCENDING, GUIConst.ACTION_SHOW_MODIFIED, GUIConst.ACTION_SHOW_UNSEND, GUIConst.ACTION_SHOW_SEND,
        GUIConst.ACTION_INSERT_TEXT, GUIConst.ACTION_INSERT_SCHEMA, GUIConst.ACTION_INSERT_STAMP, GUIConst.ACTION_SELECT_INSURANCE,
        GUIConst.ACTION_CUT, GUIConst.ACTION_COPY, GUIConst.ACTION_PASTE, GUIConst.ACTION_UNDO, GUIConst.ACTION_REDO
    };
    private IChart parent;
    private String title;
    private boolean dirty;

    /** Creates new form PatientInfoDocumentPanel
     * @param parent
     */
    public PatientInfoDocumentPanel(IChart parent) {
        this.parent = parent;
        this.title = TITLE;
        initComponents();

    }

    /** 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
    /**
     *
     * @return
     */
    @Override
    public TYPE getType() {
        return TYPE.Plugin;
    }

    private void initialize() {

        JComponent compo = createComponent();
        compo.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11));
        setLayout(new BorderLayout());

        // 保存ボタンを生成する
        JPanel cmdPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        cmdPanel.add(new JLabel(GlobalConstants.getImageIcon(INFO_BUTTON_IMAGE)));
        cmdPanel.add(new JLabel(INFO));
        saveBtn = new JButton(GlobalConstants.getImageIcon(SAVE_ICON));
        saveBtn.setEnabled(false);
        saveBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                save();
            }
        });
        cmdPanel.add(saveBtn);

        add(cmdPanel, BorderLayout.NORTH);
        add(compo, BorderLayout.CENTER);

        stateMgr = new StateContext();
        enter();
    }

    /**
     *
     */
    @Override
    public void start() {
        initialize();
    }

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

    /**
     *
     */
    @Override
    public void enter() {

        parent.getStatusPanel().setMessage("");
        getParentContext().getChartMediator().setAccepter(this);
        disableMenus();

        getParentContext().enabledAction(GUIConst.ACTION_NEW_KARTE, true);
        getParentContext().enabledAction(GUIConst.ACTION_NEW_DOCUMENT, true);
        getParentContext().enabledAction(GUIConst.ACTION_ADD_USER, GlobalVariables.isAdmin());

        if (stateMgr != null) {
            stateMgr.enter();
        }
    }

    /**
     *
     * @return
     */
    @Override
    public boolean isDirty() {
        if (stateMgr != null) {
            return stateMgr.isDirtyState();
        } else {
            return dirty;
        }
    }

    /**
     * 患者情報を更新する。
     */
    private boolean save() {

        PatientModel update = getParentContext().getPatient();
        RemotePatientDelegater pdl = new RemotePatientDelegater();
        pdl.updatePatient(update);
        stateMgr.processSavedEvent();
        /*
        DBTask task = new DBTask<Void>(getParentContext()) {

        @Override
        public Void doInBackground() throws Exception {
        pdl.updatePatient(update);
        return null;
        }

        @Override
        public void succeeded(Void result) {
        stateMgr.processSavedEvent();
        }
        };

        task.execute();
         * */

        return true;
    }

    private JComponent createComponent() {

        // 患者モデルを取得する
        PatientModel patient = getParentContext().getPatient();
        Collection<PVTHealthInsuranceModel> insList = patient.getPvtHealthInsurances();

        // 患者情報テーブルを生成する
        pModel = new PatientInfoTableModel(patient, PATIENT_ATTRS, COLUMN_NAMES);
        pTable = new JTable(pModel);
        pTable.setDefaultRenderer(Object.class, new OddEvenRowRenderer());
        TableColumn column = pTable.getColumnModel().getColumn(1);
        DefaultCellEditor de = new DefaultCellEditor(new JTextField());
        de.setClickCountToStart(2);
        column.setCellEditor(de);

        // 配置する
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.add(pTable);

        // 健康保険情報テーブルを生成する
        if (insList != null) {

            for (PVTHealthInsuranceModel insurance : insList) {
                HealthInsuranceTableModel hModel = new HealthInsuranceTableModel(
                        insurance, COLUMN_NAMES);
                JTable hTable = new JTable(hModel);
                hTable.setDefaultRenderer(Object.class,
                        new OddEvenRowRenderer());

                // 配置する
                panel.add(Box.createVerticalStrut(7));
                panel.add(hTable);
            }
        }
        JScrollPane scroller = new JScrollPane(panel);
        scroller.getViewport().setBackground(GlobalSettings.getColors(GlobalSettings.Parts.TABLE_BACKGROUND));
        return scroller;
    }

    /**
     * 
     * @return
     */
    @Override
    public boolean itLayoutSaved() {
        return true;
    }

    /**
     *
     * @return
     */
    @Override
    public String getTitle() {
        return title;
    }

    /**
     *
     * @return
     */
    @Override
    public IChart getParentContext() {
        return parent;
    }

    /**
     *
     * @return
     */
    @Override
    public boolean prepare() {
        return true;
    }

    /**
     *
     * @param dirty
     */
    @Override
    public void setDirty(boolean dirty) {
        this.dirty = dirty;
    }

    /**
     *
     * @return
     */
    public boolean isReadOnly() {
        return getParentContext().isReadOnly();
    }

    /**
     *
     */
    public void disableMenus() {
        // このウインドウに関連する全てのメニューをdisableにする
        ChartMediator mediator = getParentContext().getChartMediator();
        mediator.disableMenus(CHART_MENUS);
    }

    /**
     * 共通の警告表示を行う。
     * @param title
     * @param message
     */
    protected void warning(String title, String message) {
        Window parentWindow = SwingUtilities.getWindowAncestor(this);
        JOptionPane.showMessageDialog(parentWindow, message, GlobalConstants.getFrameTitle(title), JOptionPane.WARNING_MESSAGE);
    }

    /**
     *
     * @param command
     * @return
     */
    @Override
    public boolean dispatchChartCommand(open.dolphin.helper.IChartCommandAccepter.ChartCommand command) {
        switch (command) {
            case save:
                return save();
            case print:
                return true;
            default:
                ;
        }
        return false;
    }

    /**
     *
     * @return
     */
    @Override
    public java.util.List<JTabbedPane> getTabbedPanels() {
        return null;
    }

    /**
     *
     * @param o
     * @return
     */
    @Override
    public boolean update(Object o) {
        return true;
    }

    /**
     * 患者情報を表示する TableModel クラス。
     */
    protected class PatientInfoTableModel extends AbstractTableModel {

        private PatientModel patient; // 患者モデル
        private String[] attributes; // 属性名の配列
        private String[] columnNames; // カラム名の配列

        /**
         *
         * @param patient
         * @param attrs
         * @param columnNames
         */
        public PatientInfoTableModel(PatientModel patient, String[] attrs, String[] columnNames) {
            this.patient = patient;
            this.attributes = attrs;
            this.columnNames = columnNames;
        }

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

        @Override
        public int getRowCount() {
            return PATIENT_ATTRS.length;
        }

        @Override
        public boolean isCellEditable(int row, int col) {
            //
            // 編集可能な行である場合に true
            //
            boolean ret = false;
            if (col == 1) {
                for (int i = 0; i < EDITABLE_ROWS.length; i++) {
                    if (row == EDITABLE_ROWS[i]) {
                        ret = true;
                        break;
                    }
                }
            }
            return ret;
        }

        @Override
        public Object getValueAt(int row, int col) {

            String ret = null;

            if (col == 0) {
                // 属性名を返す
                ret = attributes[row];
            } else if (col == 1 && patient != null) {

                // 患者属性を返す
                switch (row) {
                    case 0:
                        ret = patient.getPatientId();
                        break;
                    case 1:
                        ret = patient.getFullName();
                        break;
                    case 2:
                        ret = patient.getKanaName();
                        break;
                    case 3:
                        ret = patient.getRomanName();
                        break;
                    case 4:
                        ret = patient.getGender();
                        break;
                    case 5:
                        ret = patient.getAgeBirthday();
                        break;
                    case 6:
                        ret = patient.getNationality();
                        break;
                    case 7:
                        ret = patient.getMaritalStatus();
                        break;
                    case 8:
                        ret = patient.contactZipCode();
                        break;
                    case 9:
                        ret = patient.contactAddress();
                        if (ret != null) {
                            ret = ret.replaceAll("　", " ");
                        }
                        break;
                    case 10:
                        ret = patient.getTelephone();
                        break;
                    case 11:
                        ret = patient.getMobilePhone();
                        break;
                    case 12:
                        ret = patient.getEmail();
                        break;
                }
            }
            return ret;
        }

        /**
         * 属性値を変更する。
         * @param value 属性値
         * @param row 行
         * @param col 列
         */
        @Override
        public void setValueAt(Object value, int row, int col) {

            if (value == null || value.equals("") || col == 0) {
                return;
            }

            String strValue = (String) value;
            switch (row) {
                case 3:
                    // ローマ字
                    patient.setRomanName(strValue);
                    stateMgr.processDirtyEvent();
                    break;
                case 6:
                    // 国籍
                    patient.setNationality(strValue);
                    stateMgr.processDirtyEvent();
                    break;
                case 7:
                    // 婚姻状況
                    patient.setMaritalStatus(strValue);
                    stateMgr.processDirtyEvent();
                    break;
                case 11:
                    // 携帯電話
                    patient.setMobilePhone(strValue);
                    stateMgr.processDirtyEvent();
                    break;
                case 12:
                    // 電子メール
                    patient.setEmail(strValue);
                    stateMgr.processDirtyEvent();
                    break;
            }
        }
    }

    /**
     * 保険情報を表示する TableModel クラス。
     */
    protected class HealthInsuranceTableModel extends AbstractTableModel {

        private String[] columnNames;
        private java.util.List<String[]> data;

        /**
         *
         * @param insurance
         * @param columnNames
         */
        public HealthInsuranceTableModel(PVTHealthInsuranceModel insurance,
                String[] columnNames) {
            this.columnNames = columnNames;
            data = getData(insurance);
        }

        private java.util.List getData(PVTHealthInsuranceModel insurance) {

            if (insurance == null) {
                return null;
            }

            java.util.List<String[]> list = new ArrayList<String[]>();

            String[] rowData = new String[2];
            rowData[0] = "保険種別";
            rowData[1] = insurance.getInsuranceClass();
            list.add(rowData);

            rowData = new String[2];
            rowData[0] = "保険種別コード";
            rowData[1] = insurance.getInsuranceClassCode();
            list.add(rowData);

            rowData = new String[2];
            rowData[0] = "保険者番号";
            rowData[1] = insurance.getInsuranceNumber();
            list.add(rowData);

            rowData = new String[2];
            rowData[0] = "被保険者記号";
            rowData[1] = insurance.getClientGroup();
            list.add(rowData);

            rowData = new String[2];
            rowData[0] = "被保険者番号";
            rowData[1] = insurance.getClientNumber();
            list.add(rowData);

            rowData = new String[2];
            rowData[0] = "本人家族区分";
            rowData[1] = insurance.getFamilyClass();

            if (rowData[1].equals("true")) {
                rowData[1] = "本人";
            } else if (rowData[1].equals("false")) {
                rowData[1] = "家族";
            } else {
                rowData[1] = "";
            }
            list.add(rowData);

            rowData = new String[2];
            rowData[0] = "開始日";
            rowData[1] = insurance.getStartFormatDate();
            list.add(rowData);

            rowData = new String[2];
            rowData[0] = "有効期限";
            rowData[1] = insurance.getExpiredFormatDate();
            list.add(rowData);

            String[] vals = insurance.getContinuedDisease();
            if (vals != null) {
                int count = vals.length;
                for (int i = 0; i < count; i++) {
                    rowData = new String[2];
                    rowData[0] = "継続適応疾患名";
                    rowData[1] = vals[i];
                    list.add(rowData);
                }
            }

            rowData = new String[2];
            rowData[0] = "入院時の負担率";
            rowData[1] = insurance.getPayInRatio();
            list.add(rowData);

            rowData = new String[2];
            rowData[0] = "外来時の負担率";
            rowData[1] = insurance.getPayOutRatio();
            list.add(rowData);

            PVTPublicInsuranceItemModel[] pbi = insurance.getPVTPublicInsuranceItem();
            if (pbi == null) {
                return list;
            }
            int count = pbi.length;
            for (int i = 0; i < count; i++) {
                PVTPublicInsuranceItemModel item = pbi[i];

                rowData = new String[2];
                rowData[0] = "公費の優先順位";
                rowData[1] = item.getPriority();
                list.add(rowData);

                rowData = new String[2];
                rowData[0] = "公費負担名称";
                rowData[1] = item.getProviderName();
                list.add(rowData);

                rowData = new String[2];
                rowData[0] = "負担者番号";
                rowData[1] = item.getProvider();
                list.add(rowData);

                rowData = new String[2];
                rowData[0] = "受給者番号";
                rowData[1] = item.getRecipient();
                list.add(rowData);

                rowData = new String[2];
                rowData[0] = "開始日";
                rowData[1] = item.getStartFormatDate();
                list.add(rowData);

                rowData = new String[2];
                rowData[0] = "有効期限";
                rowData[1] = item.getExpiredFormatDate();
                list.add(rowData);

                rowData = new String[2];
                rowData[0] = "負担率";
                rowData[1] = item.getPaymentRatio();
                list.add(rowData);

                rowData = new String[2];
                rowData[0] = "負担率または負担金";
                rowData[1] = item.getPaymentRatioType();
                list.add(rowData);
            }

            return list;
        }

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

        @Override
        public int getRowCount() {
            return data != null ? data.size() : 5;
        }

        @Override
        public Object getValueAt(int row, int col) {

            if (data == null) {
                return null;
            }

            if (row >= data.size()) {
                return null;
            }

            String[] rowData = (String[]) data.get(row);

            return (Object) rowData[col];
        }
    }

    abstract class State {

        public abstract void enter();
    }

    class CleanState extends State {

        @Override
        public void enter() {
            saveBtn.setEnabled(false);
            setDirty(false);
        }
    }

    class DirtyState extends State {

        @Override
        public void enter() {
            saveBtn.setEnabled(true);
        }
    }

    class StateContext {

        private CleanState cleanState = new CleanState();
        private DirtyState dirtyState = new DirtyState();
        private State curState;

        public StateContext() {
            curState = cleanState;
        }

        public void enter() {
            curState.enter();
        }

        public void processSavedEvent() {
            curState = cleanState;
            this.enter();
        }

        public void processDirtyEvent() {
            if (!isDirtyState()) {
                curState = dirtyState;
                this.enter();
            }
        }

        public boolean isDirtyState() {
            return curState == dirtyState ? true : false;
        }
    }
}
