using System;
using System.Collections.Generic;
using System.Text;
using nft.framework.drawing;

namespace nft.core.geometry {
    public struct Size3DV {
        public int VX;
        public int VY;
        public int VZ;

        internal Size3DV(Size3D src) {
            this.VX = src.sx;
            this.VY = src.sy;
            this.VZ = src.sz;
        }

        public Size3DV(Size3DV src) {
            this.VX = src.VX;
            this.VY = src.VY;
            this.VZ = src.VZ;
        }

        public Size3DV(int vx, int vy, int vz) {
            this.VX = vx;
            this.VY = vy;
            this.VZ = vz;
        }

        public override string ToString() {
            return string.Format("Size3DV({0},{1},{2})", VX, VY, VZ);
        }
    }

    public struct Point3DV {
        public int VX;
        public int VY;
        public int VZ;

        /// <summary>
        /// Do not called except from CoordinationUtil.
        /// ビューの回転が考慮されていないので、CoordinationUtil以外から使わないこと
        /// </summary>
        /// <param name="src"></param>
        internal Point3DV(Location src) {
            this.VX = src.X;
            this.VY = src.Y;
            this.VZ = src.Z;
        }

        public Point3DV(Point3DV src) {
            this.VX = src.VX;
            this.VY = src.VY;
            this.VZ = src.VZ;
        }

        public Point3DV(Point3D src) {
            this.VX = src.X;
            this.VY = src.Y;
            this.VZ = src.Z;
        }

        public Point3DV(int vx, int vy, int vz) {
            this.VX = vx;
            this.VY = vy;
            this.VZ = vz;
        }

        public override string ToString() {
            return string.Format("Point3DV({0},{1},{2})",VX, VY, VZ);
        }

        /// <summary>
        /// 位置を持たないことを示す特殊な値
        /// </summary>
        public static readonly Point3DV UNPLACED = new Point3DV(short.MinValue, short.MinValue, short.MinValue);

        #region cast operators for 'nft.framework.drawing' objects.
        public static implicit operator Point3DV(Point3D p) {
            return new Point3DV(p);
        }

        public static implicit operator Point3D(Point3DV p) {
            return new Point3D(p.VX, p.VY, p.VZ);
        }

        public static implicit operator PointF3D(Point3DV p) {
            return new PointF3D(p.VX, p.VY, p.VZ);
        }

        public static explicit operator Point3DV(PointF3D p) {
            return new Point3DV((int)p.X, (int)p.Y, (int)p.Z);
        }
        #endregion
    }

    public class Rect3DV {
        private Point3DV loc;
        public Point3DV Location { get { return new Point3DV(loc); } }
        private Size3DV size;
        public Size3DV Size { get { return new Size3DV(size); } }

		public int VX { get{ return loc.VX; }  }
		public int VY { get{ return loc.VY; }  }
		public int VZ { get{ return loc.VZ; }  }
		public int VX2 { get{ return loc.VX+size.VX; }  }
		public int VY2 { get{ return loc.VY+size.VY; }  }
		public int VZ2 { get{ return loc.VZ+size.VZ; }  }
		public int WidthX { get{ return size.VX; }  }
		public int WidthY { get{ return size.VY; }  }
		public int Height { get{ return size.VZ; }  }

        /// <summary>
        /// Do not called except from CoordinationUtil.
        /// ビューの回転が考慮されていないので、CoordinationUtil以外から使わないこと
        /// </summary>
        /// <param name="src"></param>
        internal Rect3DV(Rect3D src) {
            this.loc = new Point3DV(src.Location);
            this.size = new Size3DV(src.Size);
        }

        public Rect3DV(Point3DV pt, Size3DV sz) {
            this.loc = pt;
            this.size = sz;
        }

        public Rect3DV(int vx, int vy, int vz, int vx2, int vy2, int vz2) {
            this.loc = new Point3DV(vx,vy,vz);
            this.size = new Size3DV(vx2-vx,vy2-vy,vz2-vz);
        }

        public bool IntersectWith(Rect3DV other) {
            return (this.VX2 >= other.VX && this.VX <= other.VX2
                && this.VY2 >= other.VY && this.VY <= other.VY2);
        }

        public override string ToString() {
            return string.Format("Rect3D({0},{1},{2})+({3},{4},{5})", 
                loc.VX, loc.VY, loc.VZ, size.VX, size.VY, size.VZ);
        }

        public static Rect3DV NULL = new Rect3DV(Point3DV.UNPLACED, new Size3DV(0, 0, 0));
    }

}
