/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on ----
!  AUTHOR(S): KOGA, Junichiro
!  File : InternalHeavyFrameChase.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */
package ciss.phase_viewer.mainpanel;

import java.awt.AWTException;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;

import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;

import org.apache.log4j.Logger;

import ciss.phase_viewer.settings.GlobalProperties;
import ciss.phase_viewer.settings.PropertiesManager;

//internal frame for `heavy-weight' components ... hope it works!
public abstract class InternalHeavyFrameChase extends
        AbstractInternalFrameChase {

    private static Logger logger = Logger
            .getLogger(InternalHeavyFrameChase.class.getName());

    public InternalHeavyFrameChase() {
        super();
    }

    public InternalHeavyFrameChase(String title) {
        super(title);
    }

    public InternalHeavyFrameChase(String title, boolean b1) {
        super(title, b1);
    }

    public InternalHeavyFrameChase(String title, boolean b1, boolean b2) {
        super(title, b1, b2);
    }

    public InternalHeavyFrameChase(String title, boolean b1, boolean b2,
            boolean b3) {
        super(title, b1, b2, b3);
    }

    public InternalHeavyFrameChase(String title, boolean b1, boolean b2,
            boolean b3, boolean b4) {
        super(title, b1, b2, b3, b4);
    }

    public InternalHeavyFrameChase(String title, boolean b1, boolean b2,
            boolean b3, boolean b4, Dimension size) {
        super(title, b1, b2, b3, b4, size);
    }

    public InternalHeavyFrameChase(String title, boolean b1, boolean b2,
            boolean b3, boolean b4, Dimension size, boolean initVisible) {
        super(title, b1, b2, b3, b4, size, initVisible);
    }

    public InternalHeavyFrameChase(String title, boolean b1, boolean b2,
            boolean b3, boolean b4, int location) {
        super(title, b1, b2, b3, b4, location);
    }

    public InternalHeavyFrameChase(String title, boolean b1, boolean b2,
            boolean b3, boolean b4, Dimension size, int location) {
        super(title, b1, b2, b3, b4, size, location);
    }

    public InternalHeavyFrameChase(String title, boolean b1, boolean b2,
            boolean b3, boolean b4, Dimension size, int location,
            boolean initVisible) {
        super(title, b1, b2, b3, b4, size, location, initVisible);
    }

    private InternalHeavyFrameAdapterChase listener;

    void addListeners() {
        String listen2 = props
                .getProperty("listen_to_activation_of_internal_frame");
        if (listen2 == null || !listen2.trim().equals("false")) {
            listener = new InternalHeavyFrameAdapterChase();
            super.addInternalFrameListener(listener);
        } else {
            setLayer(((Desk) Desk.getDesktop()).getMaxLayer() + 1);
        }
    }

    public boolean isHeavyWeight() {
        return true;
    }

    private BufferedImage image;

    public void pseudoSelection() {
        if (listener == null) {
            return;
        }
        listener.activate(this);
        // try{
        // setSelected(true);
        // } catch(PropertyVetoException pve) {
        setLayer(((Desk) Desk.getDesktop()).getMaxLayer() + 1);
        // }
    }

    public void activated() {
    }

    /**
     * called every time when this frame is de-activated.
     */
    public void deactivated() {
    }

    /**
     * called every time when this frame is about to be de-activated.
     */
    public void aboutTobeDeactivated() {
    }

    /**
     * called every time when this frame is about to be activated.
     */
    public void aboutTobeActivated() {
    }

    protected abstract void stopAllAnimations();

}

class InternalHeavyFrameAdapterChase extends InternalFrameAdapter {

    private static Logger logger = Logger
            .getLogger(InternalHeavyFrameAdapterChase.class.getName());
    private Component[] buff;
    private InternalHeavyFrameChase fr;
    private Robot robot;
    private GlobalProperties props = PropertiesManager
            .getGlobalProperties(PropertiesManager.PROPERTIES_PVIEWER);
    private boolean allow_light_overlay_heavy = true;

    protected InternalHeavyFrameAdapterChase() {
        try {
            robot = new Robot();
        } catch (AWTException ex) {
            logger.error("failed to create Robot");
        }
        String str = props.getProperty("allow_light_overlay_heavy");
        if (str == null || str.equalsIgnoreCase("false")) {
            allow_light_overlay_heavy = false;
        }

    }

    protected Component[] getBuffer() {
        return this.buff;
    }

    public void internalFrameActivated(InternalFrameEvent ife) {
        fr = (InternalHeavyFrameChase) ife.getSource();
        fr.aboutTobeActivated();
        Container cont = fr.getContentPane();
        activate(fr);

        fr.selected();
        fr.activated();
    }

    protected void activate(JInternalFrame fr) {
        if (!allow_light_overlay_heavy) {
            return;
        }
        Container lcont = fr.getContentPane();
        if (buff == null) {
            return;
        }

        for (int i = 0; i < buff.length; i++) {
            if (buff[i] instanceof java.awt.Panel) {
                buff[i].setVisible(true);
            }
            // if ( buff[i] instanceof JComponent ) {
            // ((JComponent) buff[i]).revalidate();
            // }
        }

        fr.setGlassPane(new JPanel());

        fr.setLayer(0);
    }

    public void internalFrameDeactivated(InternalFrameEvent ife) {
        fr = (InternalHeavyFrameChase) ife.getSource();
        fr.aboutTobeDeactivated();
        fr.stopAllAnimations();
        Container cont = fr.getContentPane();
        deactivate(fr);
        fr.deactivated();
        logger.debug("successfully deactivated...");
    }

    protected void deactivate(JInternalFrame fr) {
        if (!allow_light_overlay_heavy) {
            return;
        }
        Container cont = fr.getContentPane();
        int locx = 0;
        int locy = 0;
        boolean hasLocation = true;
        try {
            locx = fr.getRootPane().getLocationOnScreen().x;
            locy = fr.getRootPane().getLocationOnScreen().y;
        } catch (Exception exc) {
            hasLocation = false;
        }
        logger.debug("pos: " + locx + " " + locy);

        int width = fr.getSize().width;
        int height = fr.getSize().height;

        Rectangle bounds = new Rectangle(locx, locy, width, height);
        BufferedImage image = null;

        int maxCount = 10;
        int count = 0;
        while (true) {
            if (robot != null) {
                image = robot.createScreenCapture(bounds);
            } else {
                logger.error("failed to capture screen...");
                return;
            }

            if (image != null) {
                DummyImage dummy = new DummyImage(image);
                fr.setGlassPane(dummy);
                break;
            } else {
                count++;
                if (count >= maxCount) {
                    break;
                }
            }
        }

        buff = cont.getComponents();
        if (buff != null && buff.length > 0) {
            for (int i = 0; i < buff.length; i++) {
                if (buff[i] instanceof java.awt.Panel) {
                    buff[i].setVisible(false);
                }
            }
        }

        fr.setLayer(0);
    }

    public void internalFrameClosed(InternalFrameEvent ife) {
        ((Desk) Desk.getDesktop()).scrollBarUpdate();
    }

}

class DummyImage extends JPanel {
    private BufferedImage image;

    protected DummyImage(BufferedImage image) {
        this.image = image;
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.drawImage(image, null, 0, 0);
    }
}
