// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2012 Thomas Klose & Torsten Schache, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.


using System;


namespace Hiperscan.GtkExtensions.Compiler
{
    
    public class GraphicsCompiler
    {
        public GraphicsCompiler(GraphicsObject visual_tree, GenericGraphicCompiler translator)
        {
            this.Translator = translator;
            this.VisualTree = visual_tree;
        }
        
        public void TraverseVisualTree()
        {
            this.TraverseVisualTree(this.VisualTree);
        }
        
        private void TraverseVisualTree(GraphicsObject graphics)
        {
            if (graphics is GraphicsGroup)
                this.HandleGraphicsGroup(graphics as GraphicsGroup);
            else if (graphics is GraphicsText)
                this.HandleGraphicsText(graphics as GraphicsText);
            else if (graphics is GraphicsTextParagraph)
                this.HandleGraphicsTextParagraph(graphics as GraphicsTextParagraph);
            else if (graphics is GraphicsImage)
                this.HandleGraphicsImage(graphics as GraphicsImage);
            else if (graphics is GraphicsShape)
                this.HandleGraphicsShape(graphics as GraphicsShape);
        }
        
        private void HandleGraphicsGroup(GraphicsGroup group)
        {
            this.Translator.SaveContext();
            this.Translator.PushAlpha(group.Opacity);
            this.Translator.SetTransformations(group.TransformGroup);
            
            foreach(GraphicsObject graphics in group.Children)
            {
                this.TraverseVisualTree(graphics);
            }
            
            this.Translator.SetClip(group.ClipRegion);
            this.Translator.PopAlpha();
            this.Translator.RestoreContext();
        }
        
        private void HandleGraphicsText(GraphicsText text)
        {
            this.Translator.DrawText(text);
        }
        
        private void HandleGraphicsTextParagraph(GraphicsTextParagraph paragraph)
        {
            this.Translator.DrawTextParagraph(paragraph);
        }
        
        private void HandleGraphicsImage(GraphicsImage image)
        {
            this.Translator.DrawImage(image);
        }
        
        private void HandleGraphicsShape(GraphicsShape shape)
        {
            this.Translator.NewPath();
            
            if(shape.Brush != null || shape.Pen != null)
            {
                this.Translator.NewPath();
                
                if(shape is GraphicsShapeLine)
                    this.Translator.DrawLine(shape as GraphicsShapeLine);
                else if (shape is GraphicsShapeRectangle)
                    this.Translator.DrawRectangle(shape as GraphicsShapeRectangle);
                else if (shape is GraphicsShapeCircle)
                    this.Translator.DrawCircle(shape as GraphicsShapeCircle);
                else if (shape is GraphicsShapePolygone)
                    this.Translator.DrawPolygone(shape as GraphicsShapePolygone);
                else if (shape is GraphicsShapeArc)
                    this.Translator.DrawArc(shape as GraphicsShapeArc);
                
                
                if (shape.IsClosed == true)
                    this.Translator.ClosePath();    
                
                this.Translator.SaveContext();
                if(shape.Brush == null && shape.Pen != null)
                {
                    this.Translator.SetStroke(shape.Pen);
                    this.Translator.Stroke();
                }
                else 
                {
                    if(shape.Brush != null && shape.Pen != null)
                    {
                        this.Translator.SetStroke(shape.Pen);
                        this.Translator.StrokePreverse();
                        this.Translator.SetFill(shape.Brush);
                        this.Translator.Fill();
                    }
                    else
                    {
                        this.Translator.SetFill(shape.Brush);
                        this.Translator.Fill();
                    }
                }
                this.Translator.RestoreContext();
                
            }
        }
        
        private GraphicsObject VisualTree    {get;set;}
        private GenericGraphicCompiler Translator {get;set;}
    }
}

