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

/*
 * PatientInspector.java
 *
 * Created on 2009/12/17, 13:09:40
 */
package open.dolphin.client.karte;

import java.awt.Component;
import java.awt.Rectangle;
import java.beans.EventHandler;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JViewport;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import open.dolphin.client.IChart;
import open.dolphin.client.IChartDocument;
import open.dolphin.infomodel.KarteBean;
import open.dolphin.infomodel.PatientModel;
import open.dolphin.component.DnDTabbedPane;
import open.dolphin.component.TabTransferHandler;
import open.dolphin.log.LogWriter;
import open.dolphin.plugin.IPlugin;
import open.dolphin.plugin.PluginWrapper;
import open.dolphin.utils.Persistent;

/**
 *
 * @author oda
 */
public class PatientInspector extends JPanel implements IChartDocument {

    /**
     *
     */
    public static final String TITLE = "インスペクタ";
    private BasicInfoPanel basicInfoInspector;    // 患者基本情報
    private DocumentHistoryPanel docHistory;    // 文書履歴
    private List<JTabbedPane> tabbedPanels;    // インスペクタを格納するタブペイン View
    private String keyword;
    private IChart parent;    // Context このインスペクタの親コンテキスト
    private String title;
    static private int panelCount = 3;
    static private int maxTabs = 10;

    @Override
    public IChartDocument.TYPE getType() {
        return IChartDocument.TYPE.PatientInspector;
    }

    /** Creates new form PatientInspector */
    public PatientInspector(IChart parent, String keyword) {
        this.title = TITLE;
        this.keyword = keyword;
        this.parent = parent;
        tabbedPanels = new ArrayList<JTabbedPane>();
        //   chartDocuments = getParentContext().getChartDocuments();
        initComponents();
        initCustomComponents();        // GUI を初期化する

        this.setBounds((Rectangle) Persistent.loadLayout(this.getClass().getName(), "layout", this.getBounds()));
        applyTabLocations((Properties) Persistent.loadLayout(this.getClass().getName(), "tabLocation", initialTabLocations()));
    }

    /** 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() {

        jScrollPane1 = new javax.swing.JScrollPane();
        inspector = new javax.swing.JPanel();

        setName("インスペクタ"); // NOI18N
        setLayout(new java.awt.BorderLayout());

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        inspector.setName("inspector"); // NOI18N
        inspector.setLayout(new javax.swing.BoxLayout(inspector, javax.swing.BoxLayout.Y_AXIS));
        jScrollPane1.setViewportView(inspector);

        add(jScrollPane1, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel inspector;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables

    /**
     *
     */
    public void release() {
        Persistent.saveLayout(this.getClass().getName(), "tabLocation", getTabLocations());
        Persistent.saveLayout(this.getClass().getName(), "layout", this.getBounds());
    }

    public void dispose() {
        ((DocumentHistoryPanel) docHistory).clear();        // List をクリアする
    }

    /*
     タブの位置の設定ファイルがない場合、タブの位置の初期値を設定する。
     */
    private Serializable initialTabLocations() {
        Properties result = new Properties();
        result.setProperty(DocumentHistoryPanel.TITLE, "0 0");

        int index = 0;
        int tabLocation = 1;
        for (IPlugin plugin : parent.getPlugins().values()) {
            PluginWrapper pluginWrapper = new PluginWrapper(plugin);
            if (pluginWrapper.getType() == IPlugin.Type.panel) {
                result.setProperty(pluginWrapper.getName(), Integer.toString(index % panelCount) + " " + Integer.toString(tabLocation));
                tabLocation++;
                index++;
            }
        }
        return result;
    }

    /*
     タブの位置を再現する。
     *
     */
    private void applyTabLocations(Properties layout) {
        String[][] panels = new String[panelCount][maxTabs];

        //まず、タブの位置を２次元配列に取り出す。
        for (Enumeration e = layout.propertyNames(); e.hasMoreElements();) {
            String key = (String) e.nextElement();
            String[] location = layout.getProperty(key).split(" ");
            int panelIndex = Integer.parseInt(location[0]);
            int tabLocation = Integer.parseInt(location[1]);
            panels[panelIndex][tabLocation] = key;
        }

        //配列を小さいほうから読み、タブをセットしていく。
        //これでタブの順番も保障される。
        for (int panelIndex = 0; panelIndex < panelCount; panelIndex++) {
            for (int tabIndex = 0; tabIndex < maxTabs; tabIndex++) {
                try {
                    Component plugin = (Component) parent.getChartDocument(panels[panelIndex][tabIndex]);
                    if (plugin != null) {
                        tabbedPanels.get(panelIndex).addTab(panels[panelIndex][tabIndex], plugin);
                    }
                } catch (Exception ex) {
                      LogWriter.error(getClass(), ex);
                }
            }
        }
        panels = null;
    }

    private Properties getTabLocations() {
        Properties result = new Properties();
        int panel_index = 0;
        for (JTabbedPane pane : tabbedPanels) {
            for (int index = 0; index < pane.getComponents().length; index++) {
                if (((IChartDocument) pane.getComponentAt(index)).itLayoutSaved()) {
                    result.setProperty(pane.getTitleAt(index), Integer.toString(panel_index) + " " + Integer.toString(index));
                }
            }
            panel_index++;
        }
        return result;
    }

    private void initCustomComponents() {
        basicInfoInspector = new BasicInfoPanel(getParentContext());
        DnDTabbedPane tabbedPane = null;
        for (int index = 0; index < panelCount; index++) {
            tabbedPane = new DnDTabbedPane();
            tabbedPane.addChangeListener((ChangeListener) EventHandler.create(ChangeListener.class, this, "tabChanged", ""));
            tabbedPane.setTransferHandler(new TabTransferHandler());
            tabbedPanels.add(tabbedPane);
        }

        for (JTabbedPane pane : tabbedPanels) {
            inspector.add(pane);
        }
    }

    public void tabChanged(ChangeEvent e) {
        DnDTabbedPane tabbedPane = (DnDTabbedPane) e.getSource();
        // 選択されたタブ番号に対応するプラグインをテーブルから検索する
        int index = tabbedPane.getSelectedIndex();
        String title = tabbedPane.getTitleAt(index);
        Component component = (Component) parent.getChartDocument(title);
        IChartDocument documentPanel = null;

        // KarteEditorの場合、IChartDocumentそのものでなく、それを含むJScrollPaneがコンポーネントとして
        // 返るため、そのJScrollPane中のKarteEditorをその場所から取り出している。
        // 本来はKarteEditor自体がJScrollPaneを持つべきであり、そのように変更する必要がある。
        // 変更後はこのコードは不要となる。
        if (component instanceof JScrollPane) {
            documentPanel = ((IChartDocument) ((JViewport) ((JScrollPane) component).getComponent(0)).getComponent(0));
        } else {
            documentPanel = (IChartDocument) component;
        }
        documentPanel.enter();
    }

    /**
     * コンテキストを返す。
     */
    @Override
    public IChart getParentContext() {
        return parent;
    }

    /**
     * 患者カルテを返す。
     * @return  患者カルテ
     */
    public KarteBean getKarte() {
        return getParentContext().getKarte();
    }

    /**
     * 患者を返す。
     * @return 患者
     */
    public PatientModel getPatient() {
        return getParentContext().getKarte().getPatient();
    }

    /**
     * 基本情報インスペクタを返す。
     * @return 基本情報インスペクタ
     */
    public BasicInfoPanel getBasicInfoInspector() {
        return basicInfoInspector;
    }

    /**
     * 文書履歴インスペクタを返す。
     * @return 文書履歴インスペクタ
     */
    public DocumentHistoryPanel getDocumentHistory() {
        return (DocumentHistoryPanel) docHistory;
    }

    public void setDocumentHistory(DocumentHistoryPanel docHistory) {
        this.docHistory = docHistory;
    }

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

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

    @Override
    public void start() {
    }

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

    @Override
    public void enter() {
    }

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

    /**
     *
     * @return
     */
    @Override
    public boolean isDirty() {
        for (JTabbedPane tabbedPane : tabbedPanels) {
            for (Component component : tabbedPane.getComponents()) {
                if (((IChartDocument) component).isDirty()) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     *
     * @param dirty
     */
    @Override
    public void setDirty(boolean dirty) {
    }

    @Override
    public boolean dispatchChartCommand(ChartCommand command) {
        return false;
    }

    @Override
    public List<JTabbedPane> getTabbedPanels() {
        return (List<JTabbedPane>) tabbedPanels;
    }

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