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

package com.sun.javafx.tk.quantum;

import java.nio.IntBuffer;

import com.sun.glass.ui.Screen;
import com.sun.javafx.geom.CameraImpl;
import com.sun.prism.Graphics;
import com.sun.prism.GraphicsPipeline;
import com.sun.prism.RTTexture;
import com.sun.prism.impl.Disposer;
import com.sun.prism.paint.Color;

/**
 * @author Artem Ananiev
 * @author Morris Meyer
 */
public class EmbeddedPainter extends AbstractPainter implements Runnable {
    
    private RTTexture       texture;
    private EmbeddedScene   escene;

    protected EmbeddedPainter(EmbeddedScene es) {
        super(es);
        setRoot(scene.root);
        escene = es;
    }
    
    @Override protected boolean validateStageGraphics() {
        boolean valid = super.validateStageGraphics();
        
        if (!valid) {
            return false;
        }
        
        if (escene.host == null) {
            return false;
        }

        Screen mainScreen = Screen.getMainScreen();
        GraphicsPipeline pipeline = GraphicsPipeline.getPipeline();
        factory = pipeline.getResourceFactory(mainScreen);
        
        if (!factory.isDeviceReady()) {
            return false;
        }
        
        if ((escene.width <= 0) || (escene.height <= 0)) {
            return false;
        }

        setPaintBounds(escene.width, escene.height);
        
        return true;
    }
        
    @Override public void run() {
        if (validateStageGraphics() == false) {
            return;
        }

        context = factory.createRenderingContext(null);
        escene.sizeLock.lock();
        
        try {
            context.begin();
            
            if ((texture == null) || (escene.textureBits == null) || escene.needsReset) {
                texture = factory.createRTTexture(escene.width, escene.height);
                if (texture == null) {
                    return;
                }
                escene.textureBits = IntBuffer.allocate(escene.width * escene.height);
                if (escene.textureBits == null) {
                    return;
                }
                escene.needsReset = false;
            }

            Graphics g = texture.createGraphics();
            if (g == null) {
                escene.needsReset = true;
                scene.entireSceneNeedsRepaint();
                return;
            }
            paintImpl(g);
            
            escene.textureBits.rewind();
            texture.readPixels(escene.textureBits);
            
            escene.host.repaint();
        } catch (Throwable th) {
            th.printStackTrace(System.err);
        } finally {
            Disposer.cleanUp();
            context.end();
            escene.sizeLock.unlock();
        }
    }
    
    @Override protected void doPaint(Graphics g) {
        scene.clearEntireSceneDirty();
        g.setDepthBuffer(scene.hasDepthBuffer());
        g.clear(Color.TRANSPARENT);
        if (scene.fillPaint != null) {
            g.getRenderTarget().setOpaque(scene.fillPaint.isOpaque());
            g.setPaint(scene.fillPaint);
            g.fillQuad(0, 0, escene.width, escene.height);
        }
        g.setCamera(scene.camera);
        scene.root.render(g);
    }

    @Override protected CameraImpl getCamera() {
        if (escene != null) {
            return escene.camera;
        }
        return null;
    }
}
