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

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

        // A henger sugara és magassága
        private double rad, height;
        private int div;

        #region Public properties
        public double Height {
            get { return height; }
            set { height = value; }
        }

        public double Radius {
            get { return rad; }
            set { rad = value; }
        }

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

        public Cylinder(double rad, double height, int div, Point3D ct) {
            this.rad = rad;
            this.height = height;
            this.div = div;
            if (ct == null) this.center = new Point3D(0.0, 0.0, 0.0); else this.center = ct;
            this.e1 = new Point3D(rad, 0.0, 0.0);
            this.e2 = new Point3D(0.0, rad, 0.0);
            this.e3 = new Point3D(0.0, 0.0, height / 2);
            this.UpperCorner = new Point3D(rad, rad, height / 2);
            this.LowerCorner = new Point3D(-rad, -rad, -height / 2);
            MeshTesselation();
        }

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

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


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

        public override void MeshTesselation() {
            mesh = new BRep();
            double step = 360.0 / (double)div;

            #region Vertices
            for (int i = 0; i < div; i++) {
                mesh.Vertices.Add(new Point3D(
                    (rad * Math.Cos(i * step * Math.PI / 180.0)),
                    (rad * Math.Sin(i * step * Math.PI / 180.0)),
                    -height / 2));
            }
            for (int i = 0; i < div; i++) {
                mesh.Vertices.Add(new Point3D(
                    (rad * Math.Cos(i * step * Math.PI / 180.0)),
                    (rad * Math.Sin(i * step * Math.PI / 180.0)),
                    height / 2));
            }
            mesh.Vertices.Add(new Point3D(0.0, 0.0, -height / 2));
            mesh.Vertices.Add(new Point3D(0.0, 0.0, height / 2));
            #endregion

            #region Edges
            for (int i = 0; i < div; ++i) {
                mesh.Edges.Add(new Edge(i, (i + 1) % div));
                mesh.Edges.Add(new Edge(i + div, (i + 1) % div + div));
                mesh.Edges.Add(new Edge(i, i + div));
            }
            #endregion

            #region Faces
            for (int i = 0; i < div; ++i) {
                mesh.Faces.Add(new Face(i, (i + 1) % div, i + div));
                mesh.Faces.Add(new Face((i + 1) % div, (i + 1) % div + div, i + div));
                mesh.Faces.Add(new Face((i + 1) % div, i, mesh.Vertices.Count - 2));
                mesh.Faces.Add(new Face(i + div, (i + 1) % div + div, mesh.Vertices.Count - 1));
            }
            #endregion
        }

        public override void ChangeParams() {
            NewCylinder ns = new NewCylinder();
            ns.Text = "Modify Cylinder";
            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.rad = ns.rad;
            this.height = ns.height;
            this.div = ns.div;
            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);
            this.e1 = new Point3D(rad, 0.0, 0.0);
            this.e2 = new Point3D(0.0, rad, 0.0);
            this.e3 = new Point3D(0.0, 0.0, height / 2);
            this.UpperCorner = new Point3D(rad, rad, height / 2);
            this.LowerCorner = new Point3D(-rad, -rad, -height / 2);
            base.ChangeParams();
        }
    }
}
