/*
 * Copyright 2016 MovingBlocks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.terasology.rendering.dag.nodes;

import org.terasology.assets.ResourceUrn;
import org.terasology.config.Config;
import org.terasology.config.RenderingConfig;
import org.terasology.monitoring.PerformanceMonitor;
import org.terasology.registry.In;
import org.terasology.rendering.assets.material.Material;
import org.terasology.rendering.dag.AbstractNode;
import static org.terasology.rendering.opengl.DefaultDynamicFBOs.READ_ONLY_GBUFFER;
import org.terasology.rendering.opengl.FBO;
import org.terasology.rendering.opengl.FBOConfig;
import static org.terasology.rendering.opengl.ScalingFactors.FULL_SCALE;
import org.terasology.rendering.opengl.fbms.DisplayResolutionDependentFBOs;
import org.terasology.rendering.world.WorldRenderer;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.terasology.rendering.opengl.OpenGLUtils.bindDisplay;
import static org.terasology.rendering.opengl.OpenGLUtils.renderFullscreenQuad;
import static org.terasology.rendering.opengl.OpenGLUtils.setViewportToSizeOf;

/**
 * TODO: Add diagram of this node
 */
public class OutlineNode extends AbstractNode {
    public static final ResourceUrn OUTLINE = new ResourceUrn("engine:outline");

    @In
    private DisplayResolutionDependentFBOs displayResolutionDependentFBOs;

    @In
    private WorldRenderer worldRenderer;

    @In
    private Config config;

    private RenderingConfig renderingConfig;
    private Material outline;
    private FBO outlineFBO;


    @Override
    public void initialise() {
        renderingConfig = config.getRendering();
        outline = worldRenderer.getMaterial("engine:prog.sobel");
        requiresFBO(new FBOConfig(OUTLINE, FULL_SCALE, FBO.Type.DEFAULT), displayResolutionDependentFBOs);
    }

    /**
     * Enabled by the "outline" option in the render settings, this method generates
     * landscape/objects outlines and stores them into a buffer in its own FBO. The
     * stored image is eventually combined with others.
     * <p>
     * The outlines visually separate a given object (including the landscape) or parts of it
     * from sufficiently distant objects it overlaps. It is effectively a depth-based edge
     * detection technique and internally uses a Sobel operator.
     * <p>
     * For further information see: http://en.wikipedia.org/wiki/Sobel_operator
     */
    @Override
    public void process() {
        if (renderingConfig.isOutline()) { // TODO: define state changes after this check is eliminated
            PerformanceMonitor.startActivity("rendering/outline");
            outlineFBO = displayResolutionDependentFBOs.get(OUTLINE);

            outline.enable();

            // TODO: verify inputs: shouldn't there be a texture binding here?
            outlineFBO.bind();

            setViewportToSizeOf(outlineFBO);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // TODO: verify this is necessary

            renderFullscreenQuad();

            bindDisplay();  // TODO: verify this is necessary
            setViewportToSizeOf(READ_ONLY_GBUFFER); // TODO: verify this is necessary
            PerformanceMonitor.endActivity();
        }
    }
}

@@ -884,32 +884,34 @@
 ing.
-assets.material.Material
+dag.ConditionDependentNode
 ;%0Aim
@@ -944,28 +944,36 @@
 ing.dag.
-AbstractNode
+stateChanges.BindFBO
 ;%0Aimport
@@ -965,39 +965,32 @@
 BindFBO;%0Aimport 
-static 
 org.terasology.r
@@ -1002,51 +1002,39 @@
 ing.
-opengl.DefaultDynamicFBOs.READ_ONLY_GBUFFER
+dag.stateChanges.EnableMaterial
 ;%0Aim
@@ -1129,81 +1129,8 @@
 ig;%0A
-import static org.terasology.rendering.opengl.ScalingFactors.FULL_SCALE;%0A
 impo
@@ -1614,39 +1614,33 @@
 ngl.
-OpenGLUtils.setViewportToSizeOf
+ScalingFactors.FULL_SCALE
 ;%0A%0A/
@@ -1717,15 +1717,25 @@
 nds 
-Abstrac
+ConditionDependen
 tNod
@@ -2039,67 +2039,8 @@
 ig;%0A
-    private Material outline;%0A    private FBO outlineFBO;%0A%0A
 %0A   
@@ -2142,170 +2142,464 @@
     
-outline = worldRenderer.getMaterial(%22engine:prog.sobel%22);%0A        requiresFBO(new FBOConfig(OUTLINE, FULL_SCALE, FBO.Type.DEFAULT), displayResolutionDependentFBOs
+renderingConfig.subscribe(renderingConfig.OUTLINE, this);%0A        requiresCondition(() -%3E renderingConfig.isOutline());%0A        requiresFBO(new FBOConfig(OUTLINE, FULL_SCALE, FBO.Type.DEFAULT), displayResolutionDependentFBOs);%0A        addDesiredStateChange(new EnableMaterial(%22engine:prog.sobel%22));%0A        // TODO: verify inputs: shouldn't there be a texture binding here?%0A        addDesiredStateChange(new BindFBO(OUTLINE, displayResolutionDependentFBOs)
 );%0A 
@@ -3251,433 +3251,64 @@
     
-if (renderingConfig.isOutline()) %7B // TODO: define state changes after this check is eliminated%0A            PerformanceMonitor.startActivity(%22rendering/outline%22);%0A            outlineFBO = displayResolutionDependentFBOs.get(OUTLINE);%0A%0A            outline.enable();%0A%0A            // TODO: verify inputs: shouldn't there be a texture binding here?%0A            outlineFBO.bind();%0A%0A            setViewportToSizeOf(outlineFBO);%0A    
+PerformanceMonitor.startActivity(%22rendering/outline%22);%0A%0A
     
@@ -3397,28 +3397,24 @@
 cessary%0A
-%0A   
         
  renderF
@@ -3401,25 +3401,24 @@
 ary%0A        
- 
 renderFullsc
@@ -3429,21 +3429,16 @@
 Quad();%0A
-%0A    
         
@@ -3491,98 +3491,9 @@
 ary%0A
-            setViewportToSizeOf(READ_ONLY_GBUFFER); // TODO: verify this is necessary%0A    
+%0A
     
@@ -3534,17 +3534,8 @@
 ();%0A
-        %7D
 %0A   

Add desiredStateChanges to PrePostCompositeNode