#region Using directives

using System;
using System.Collections;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Math;
using OpenTK.Input;
using OpenTK.Platform;

#endregion

namespace DataProcessing
{
    public class Segment : IComparable
    {
        #region variable definitions

        private float maxX;
        private float minX;
        private float maxY;
        private float minY;
        private float maxZ;
        private float minZ;

        private float centreX;
        private float centreY;
        private float centreZ;

        private float volume;

        private string semantic = "none";

        public float MaxX
        {
            get { return maxX; }
            set { maxX = value; }
        }

        public float MinX
        {
            get { return minX; }
            set { minX = value; }
        }

        public float MaxY
        {
            get { return maxY; }
            set { maxY = value; }
        }

        public float MinY
        {
            get { return minY; }
            set { minY = value; }
        }

        public float MaxZ
        {
            get { return maxZ; }
            set { maxZ = value; }
        }

        public float MinZ
        {
            get { return minZ; }
            set { minZ = value; }
        }

        public float CentreX
        {
            get { return centreX; }
            set { centreX = value; }
        }

        public float CentreY
        {
            get { return centreY; }
            set { centreY = value; }
        }

        public float CentreZ
        {
            get { return centreZ; }
            set { centreZ = value; }
        }

        public float Volume
        {
            get { return volume; }
            set { volume = value; }
        }

        public string Semantic
        {
            get { return semantic; }
            set { semantic = value; }
        }

        #endregion define variables

        //konstruktor
        public Segment(float newMaxX, float newMinX, float newMaxY, float newMinY, float newMaxZ, float newMinZ)
        {
            maxX = newMaxX;
            minX = newMinX;
            maxY = newMaxY;
            minY = newMinY;
            maxZ = newMaxZ;
            minZ = newMinZ;

            centreX = maxX - minX;
            centreY = maxY - minY;
            centreZ = maxZ - minZ;

            CalculateVolume();
        }

        //pretizeny konstruktor
        public Segment(float X, float Y, float Z, float edge)
        {
            centreX = X;
            centreY = Y;
            centreZ = Z;            

            maxX = X + edge / 2;
            minX = X - edge / 2;
            maxY = Y + edge / 2; 
            minY = Y - edge / 2;
            maxZ = Z + edge / 2;
            minZ = Z - edge / 2;

            CalculateVolume();
        }

        //objem
        private void CalculateVolume()
        {
            volume = Math.Abs((maxX - minX) * (maxY - minY) * (maxZ - minZ));
        }

        //test pro pohlcovani mensi segmentu zda jsou obsazeny v tomto, s nastavitelnou toleranci
        public bool Contains(Segment segment, int tolerance)
        {
            if (segment.MinX < minX - tolerance || segment.MaxX > maxX + tolerance)
                return false;

            if (segment.MinY < minY - tolerance || segment.MaxY > maxY + tolerance)
                return false;

            if (segment.MinZ < minZ - tolerance || segment.MaxZ > maxZ + tolerance)
                return false;

            return true;
        } 

        //vykresleni segmentu
        public void DrawSegment(string type)
        {         
            //obarveni?
            if (type == "semantic")
            {
                if (semantic == "floor")
                    GL.Color3(0.0, 1.0, 0.0);
                else if (semantic == "ceiling")
                    GL.Color3(0.0, 0.0, 1.0);
            }

            GL.Begin(BeginMode.Quads);
            // Spodní stěna
            GL.Normal3(0.0f, -1.0f, 0.0f);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(maxX, minY, minZ);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(minX, minY, minZ);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(minX, minY, maxZ);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(maxX, minY, maxZ);
            // Přední stěna
            GL.Normal3(0.0f, 0.0f, 1.0f);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(minX, minY, maxZ);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(maxX, minY, maxZ);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(maxX, maxY, maxZ);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(minX, maxY, maxZ);
            // Zadní stěna
            GL.Normal3(0.0f, 0.0f, -1.0f);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(minX, minY, minZ);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(minX, maxY, minZ);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(maxX, maxY, minZ);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(maxX, minY, minZ);
            // Pravá stěna
            GL.Normal3(1.0f, 0.0f, 0.0f);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(maxX, minY, minZ);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(maxX, maxY, minZ);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(maxX, maxY, maxZ);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(maxX, minY, maxZ);
            // Levá stěna
            GL.Normal3(-1.0f, 0.0f, 0.0f);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(minX, minY, minZ);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(minX, minY, maxZ);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(minX, maxY, maxZ);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(minX, maxY, minZ);
            // Horní stěna
            GL.Normal3(0.0f, 1.0f, 0.0f);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(minX, maxY, minZ);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(minX, maxY, maxZ);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(maxX, maxY, maxZ);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(maxX, maxY, minZ);

            GL.End();
        }

        public int CompareTo(object value)
        {
            return volume.CompareTo(((Segment)value).volume);
        }
    }
}
