using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using DefaultEffect = StockEffects.DefaultEffect;
using nft.framework.drawing;
using System.Diagnostics;

namespace nft.xna
{
    internal class Scene
    {
        static public Matrix IsometricView = new Matrix(
                    1f, 0.5f, 0.5f, 0,
                    0f, 1f, -1f, 0,
                    -1f, 0.5f, 0.5f, 0,
                    0.5f, 0, 0, 1);

        static private DefaultEffect effect = null;
        static private Matrix Camera;

        public static Matrix LastProject {
            get { return effect.Projection; }
        }
        public static Matrix LastCamera {
            get { return Camera; }
        }

        public static DefaultEffect Prepare(XnaSurface surface) {
            if (effect == null) {
                effect = CreateDefaultEffect(surface);
            } else {
                Prepare2(effect, surface);
            }
            return effect;
        }

        public static DefaultEffect ResetAll(XnaSurface surface) {
            effect = CreateDefaultEffect(surface);
            return effect;
        }

        public static Vector3 Unproject(XnaSurface surface, Vector3 vpos) {
            PointF3D pc = surface.CameraPosition;
            Viewport vw = new Viewport(0,0,surface.width,surface.height);

            //Matrix View = Matrix.CreateLookAt
            //(
            //    new Vector3(pc.X, pc.Y, pc.Z - 10),   //カメラの位置
            //    new Vector3(pc.X, pc.Y, pc.Z - 5),   //カメラの見る点
            //    new Vector3(0, 1, 0)    //カメラの上向きベクトル。(0, -1, 0)にすると画面が上下逆になる
            //);
            //Matrix Projection = Matrix.CreateOrthographic
            //(
            //    surface.width, surface.height,
            //    -800f,      //カメラからこれより近い物体は画面に映らない
            //    1000f    //カメラからこれより遠い物体は画面に映らない
            //);
            vpos = vw.Unproject(vpos, effect.Projection, effect.View, Matrix.Identity);
            return vpos;
        }

        public static Vector3 Project(XnaSurface surface, Vector3 wpos) {
            PointF3D pc = surface.CameraPosition;
            Viewport vw = new Viewport(0, 0, surface.width, surface.height);

            //Matrix View = Matrix.CreateLookAt
            //(
            //    new Vector3(pc.X, pc.Y, pc.Z - 10),   //カメラの位置
            //    new Vector3(pc.X, pc.Y, pc.Z - 5),   //カメラの見る点
            //    new Vector3(0, 1, 0)    //カメラの上向きベクトル。(0, -1, 0)にすると画面が上下逆になる
            //);
            //Matrix Projection = Matrix.CreateOrthographic
            //(
            //    surface.width, surface.height,
            //    -800f,      //カメラからこれより近い物体は画面に映らない
            //    1000f    //カメラからこれより遠い物体は画面に映らない
            //);
            wpos = vw.Project(wpos, effect.Projection, effect.View, Matrix.Identity);
            return wpos;
        }


        public static DefaultEffect CreateDefaultEffect(XnaSurface surface) {
            GraphicsDevice dev = surface.GraphicsDevice;
            DefaultEffect ef = new DefaultEffect(dev) {
                World = Matrix.Identity
            };
            Prepare2(ef, surface);
            return ef;
        }


        private static void Prepare2(DefaultEffect ef, XnaSurface surface){
            //surface.GraphicsDevice.SetRenderTargets(surface.WorkTarget(0));
            int vw = surface.width;
            int vh = surface.height;
            //Vector3 pc = XnaUtil.ToVector3(surface.CameraPosition);
            PointF3D pc = surface.CameraPosition;
            Camera = Matrix.CreateLookAt
            (
                new Vector3(pc.X, pc.Y, pc.Z-10),   //カメラの位置
                new Vector3(pc.X, pc.Y, pc.Z-5),   //カメラの見る点
                new Vector3(0, 1, 0)    //カメラの上向きベクトル。(0, -1, 0)にすると画面が上下逆になる
            );
            ef.View = IsometricView * Camera;
            ef.Projection = Matrix.CreateOrthographic
            (
                vw, vh,
                -800f,      //カメラからこれより近い物体は画面に映らない
                1000f    //カメラからこれより遠い物体は画面に映らない
            );
        }

    }
}
