using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

namespace CSGBuilder {
    [Serializable()]
    class Cone : Solid {
        public static int counter = 1;

        // A kúp alapkörének sugara és magassága
        private double radius, height;
        // A felosztás finomsága 1..360
        private int div;

        #region Public properties
        public double Radius {
            get { return radius; }
            set { radius = value; }
        }

        public double Height {
            get { return height; }
            set { height = value; }
        }

        public int Div {
            get { return div; }
            set { div = value; }
        }
        #endregion

        public Cone(double radius, double height, int div, Point3D ct) {
            this.radius = radius;
            this.height = height;
            this.div = div;
            // Középpont megadása
            if (ct == null) this.center = new Point3D(0.0, 0.0, 0.0); else this.center = ct;
            // A tengelyirányú vektorok
            this.e1 = new Point3D(radius, 0.0, 0.0);
            this.e2 = new Point3D(0.0, radius, 0.0);
            this.e3 = new Point3D(0.0, 0.0, height);
            // A befoglaló téglatest
            this.UpperCorner = new Point3D(radius, radius, height);
            this.LowerCorner = new Point3D(-radius, -radius, 0.0);
            MeshTesselation();            
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context) {
            base.GetObjectData(info, context);
            info.AddValue("Radius", radius);
            info.AddValue("Height", height);
            info.AddValue("Div", div);
        }

        public Cone(SerializationInfo info, StreamingContext context) : base(info, context) {
            radius = info.GetDouble("Radius");
            height = info.GetDouble("Height");
            div = info.GetInt32("Div");
        }

        public override string SolidType() {
            return "Cone";
        }

        public override void MeshTesselation() {
            mesh = new BRep();
            // Ennyi fokonként kell lépkedni
            double step = 360.0 / (double)div;

            for (double i = 0; i < 360.0; i += step)
                mesh.Vertices.Add(new Point3D(
                    radius * Math.Cos(i * Math.PI / 180.0),
                    radius * Math.Sin(i * Math.PI / 180.0),
                    0.0));
            // Az alapkörlap középpontja
            mesh.Vertices.Add(new Point3D(0.0, 0.0, 0.0));
            // A kúp csúcsa
            mesh.Vertices.Add(new Point3D(0.0, 0.0, height));

            int d1 = mesh.Vertices.Count - 2;
            int d2 = mesh.Vertices.Count - 1;

            // A kúp élei
            for (int i = 0; i < d1; i++)
                mesh.Edges.Add(new Edge(i, (i + 1) % d1));
            for (int i = 0; i < d1; i++)
                mesh.Edges.Add(new Edge(i, d1));
            for (int i = 0; i < d1; i++)
                mesh.Edges.Add(new Edge(i, d2));

            // A kúp lapjai
            for (int i = 0; i < d1; i++)
                mesh.Faces.Add(new Face(i, d1, (i + 1) % d1));
            for (int i = 0; i < d1; i++)
                mesh.Faces.Add(new Face(i, (i + 1) % d1, d2));
        }

        public override void ChangeParams() {
            NewCone ns = new NewCone();
            ns.Text = "Modify Cone";
            ns.tbRad.Text = this.Radius.ToString();
            ns.tbHeight.Text = this.Height.ToString();
            ns.tbDiv.Text = this.Div.ToString();
            if (this.center.X != 0.0 || this.center.Y != 0.0 || this.center.Z != 0.0) {
                ns.cbCenter.Checked = false;
                ns.tbCX.Text = this.center.X.ToString();
                ns.tbCY.Text = this.center.Y.ToString();
                ns.tbCZ.Text = this.center.Z.ToString();
            } else ns.cbCenter.Checked = true;
            if (ns.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) return;
            this.radius = ns.rad;
            this.height = ns.height;
            this.div = ns.div;
            // Középpont megadása
            if (ns.cbCenter.Checked)
                this.center = new Point3D(0.0, 0.0, 0.0);
            else
                this.center = new Point3D(ns.cx, ns.cy, ns.cz);
            // A tengelyirányú vektorok
            this.e1 = new Point3D(radius, 0.0, 0.0);
            this.e2 = new Point3D(0.0, radius, 0.0);
            this.e3 = new Point3D(0.0, 0.0, height);
            // A befoglaló téglatest
            this.UpperCorner = new Point3D(radius, radius, height);
            this.LowerCorner = new Point3D(-radius, -radius, 0.0);
            base.ChangeParams();
        }
    }
}
