/*
 * Copyright (c) 2008, 2011, Oracle  and/or its affiliates. All rights reserved.
 *
 * Use is subject to license terms.
 */

package com.sun.javafx.tk.quantum;

import java.nio.ByteOrder;
import java.util.concurrent.Future;

import com.sun.glass.ui.Application;
import com.sun.glass.ui.Cursor;
import com.sun.glass.ui.Pixels;
import com.sun.glass.ui.View;
import com.sun.glass.ui.Window;
import com.sun.javafx.cursor.CursorFrame;
import com.sun.javafx.geom.CameraImpl;
import com.sun.javafx.sg.PGNode;
import com.sun.javafx.sg.prism.NGNode;

public class ViewScene extends GlassScene {

    private static final String UNSUPPORTED_FORMAT = 
        "Transparent windows only supported for BYTE_BGRA_PRE format on LITTLE_ENDIAN machines";
    

    private View        platformView;
    private PrismPen    pen;

    public ViewScene(boolean verbose, boolean depthBuffer) {
        super(verbose, depthBuffer);

        this.pen = new PrismPen(this, depthBuffer);
        this.platformView = Application.GetApplication().createView(this.pen);
        this.platformView.setEventHandler(new GlassViewEventHandler(this));
    }

    @Override protected boolean isSynchronous() {
        if (pen != null) {
            ViewPainter vp = pen.getPainter();
            if (vp != null && vp instanceof PresentingPainter) {
                return true;
            }
        }
        return false;
    }

    protected View getPlatformView() {
        return this.platformView;
    }
    
    protected Future getPenFuture() {
        return pen.getFuture();
    }

    public void uploadPixels(Pixels pixels) {
        if (platformView != null) {
            platformView.uploadPixels(pixels);
        }
    }
    
    protected PrismPen getPen() {
        return pen;
    }

    @Override
    public void setGlassStage(GlassStage stage) {
        super.setGlassStage(stage);
        

        if (stage != null) {
            WindowStage     wstage  = (WindowStage)stage;
            ViewPainter     painter = null;

            if (wstage.needsUpdateWindow()) {
                if (Pixels.getNativeFormat() != Pixels.Format.BYTE_BGRA_PRE ||
                    ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) {
                    throw new UnsupportedOperationException(UNSUPPORTED_FORMAT);
                }
                painter = new UploadingPainter(this, pen);
            } else {
                painter = new PresentingPainter(this, pen);
            }
            pen.setPainter(painter);
            painter.setRoot((NGNode)getRoot());
        }
    }

    WindowStage getWindowStage() {
        return (WindowStage)glassStage;
    }

    /* com.sun.javafx.tk.TKScene */

    @Override public void setScene(Object scene) {
        if (scene == null) {
            // Setting scene to null is a dispose operation
            if (this.platformView != null) {
                this.platformView.close();
                this.platformView = null;
            }
        }
    }
    
    @Override public void setRoot(PGNode root) {
        super.setRoot(root);
        ViewPainter vp = pen.getPainter();
        if (vp != null) {
            vp.setRoot((NGNode)root);
        }
    }

    @Override
    public void setCamera(CameraImpl camera) {
        super.setCamera(camera);
        this.pen.setCamera(camera);
    }

    @Override
    public void setFillPaint(Object fillPaint) {
        super.setFillPaint(fillPaint);
    }

    @Override
    public void setCursor(final Object cursor) {
        super.setCursor(cursor);
        Application.postOnEventQueue(new Runnable() {
            @Override
            public void run() {
                final CursorFrame cursorFrame = (CursorFrame) cursor;
                final Cursor platformCursor =
                        CursorUtils.getPlatformCursor(cursorFrame);
                
                if (platformView != null) {
                    Window window = platformView.getWindow();
                    if (window != null) {
                        window.setCursor(platformCursor);
                    }
                }
            }
        });
    }

    @Override void repaint() {
        pen.repaint();
    }
    
    @Override
    public void enableInputMethodEvents(boolean enable) {
        platformView.enableInputMethodEvents(enable);
    }

    @Override public void sceneChanged() {
        //Thread.dumpStack();
        super.sceneChanged();
    }
}

