/*
 * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 */

package com.sun.javafx.tk.quantum;

import java.util.List;

import javafx.application.Platform;

import com.sun.javafx.embed.AbstractEvents;
import com.sun.javafx.embed.EmbeddedStageInterface;
import com.sun.javafx.embed.HostInterface;
import com.sun.javafx.tk.TKScene;
import com.sun.javafx.tk.TKStageListener;
import com.sun.javafx.tk.Toolkit;
import com.sun.prism.impl.PrismSettings;

/**
 * @author Artem Ananiev
 */
public class EmbeddedStage extends GlassStage implements EmbeddedStageInterface {

    private HostInterface host;

    private boolean visible = false;
    
    public EmbeddedStage(HostInterface host) {
        super(PrismSettings.verbose);
        
        this.host = host;
    }

    // TKStage methods

    @Override
    public TKScene createTKScene(boolean depthBuffer) {
        return new EmbeddedScene(host, depthBuffer);
    }

    @Override
    public void setScene(TKScene scene) {
        if (scene != null) {
            assert scene instanceof EmbeddedScene;
        }
        super.setScene(scene);
    }

    @Override
    public void setTKStageListener(TKStageListener listener) {
        this.stageListener = listener;
    }

    @Override
    public void setBounds(float x, float y, boolean xSet, boolean ySet,
                          float w, float h, float cw, float ch,
                          float xGravity, float yGravity)
    {
        if (verbose) {
            System.err.println("EmbeddedStage.setBounds: x=" + x + " y=" + y + " xSet=" + xSet + " ySet=" + ySet +
                               " w=" + w + " h=" + " cw=" + cw + " ch=" + ch);
        }
        float newW = w > 0 ? w : cw;
        float newH = h > 0 ? h : ch;
        if ((newW > 0) && (newH > 0)) {
            host.setPreferredSize((int)newW, (int)newH);
        }
    }

    @Override public void setMinimumSize(int minWidth, int minHeight) {
        // This is a no-op for embedded stages
    }

    @Override public void setMaximumSize(int maxWidth, int maxHeight) {
        // This is a no-op for embedded stages
    }

    @Override
    protected void setPlatformEnabled(boolean enabled) {
        host.setEnabled(enabled);
    }

    @Override
    protected void requestToFront() {}

    @Override
    public void setIcons(List icons) {
        if (verbose) {
            System.err.println("EmbeddedStage.setIcons");
        }
    }

    @Override
    public void setTitle(String title) {
        if (verbose) {
            System.err.println("EmbeddedStage.setTitle " + title);
        }
    }

    @Override
    public void setVisible(boolean visible) {
        this.visible = visible;
        host.setEmbeddedStage(visible ? this : null);
        super.setVisible(visible);
    }

    @Override
    public void setOpacity(float opacity) {
//        host.setOpacity(opacity);
    }

    @Override
    public void setIconified(boolean iconified) {
        if (verbose) {
            System.err.println("EmbeddedScene.setIconified " + iconified);
        }
    }

    @Override
    public void setResizable(boolean resizable) {
        if (verbose) {
            System.err.println("EmbeddedStage.setResizable " + resizable);
        }
    }

    @Override
    public void setFullScreen(boolean fullScreen) {
        if (verbose) {
            System.err.println("EmbeddedStage.setFullScreen " + fullScreen);
        }
    }

    @Override
    public void requestFocus() {
        if (!host.requestFocus()) {
            return;
        }
        super.requestFocus();
    }

    @Override
    public void toBack() {
        if (verbose) {
            System.err.println("EmbeddedStage.toBack");
        }
    }

    @Override
    public void toFront() {
        if (verbose) {
            System.err.println("EmbeddedStage.toFront");
        }
    }

    //TODO: implement grabFocus()/ungrabFocus()
    @Override public boolean grabFocus() {
        return false;
    }

    @Override public void ungrabFocus() {
    }

    // EmbeddedStageInterface methods

    @Override
    public void setLocation(final int x, final int y) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                if (stageListener != null) {
                    stageListener.changedLocation(x, y);
                }
            }
        };
        // setLocation() can be called on both FX and Swing/SWT/etc threads
        if (Toolkit.getToolkit().isFxUserThread()) {
            r.run();
        } else {
            Platform.runLater(r);
        }
    }

    @Override
    public void setSize(final int width, final int height) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                if (stageListener != null) {
                    stageListener.changedSize(width, height);
                }
            }
        };
        // setSize() can be called on both FX and Swing/SWT/etc threads
        if (Toolkit.getToolkit().isFxUserThread()) {
            r.run();
        } else {
            Platform.runLater(r);
        }
    }

    @Override
    public void setFocused(final boolean focused, final int focusCause) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                if (stageListener != null) {
                    stageListener.changedFocused(focused,
                            AbstractEvents.focusCauseToPeerFocusCause(focusCause));
                }
            }
        };
        // setFocused() can be called on both FX and Swing/SWT/etc threads
        if (Toolkit.getToolkit().isFxUserThread()) {
            r.run();
        } else {
            Platform.runLater(r);
        }
    }
}
