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

namespace nft.core.geometry {
    /// <summary>
    /// Parameters specifies conversion from 3D world into 2D screen view
    /// </summary>
    public class ViewFactor {

        public ViewFactor(InterCardinalDirection dir, ZoomScale scale, Weather weather, DayNight daynight) {
            this.viewDir = dir;
            this.scale = scale;
            this.weather = weather;
            this.daynight = daynight;
        }

        public ViewFactor(InterCardinalDirection dir, ZoomScale scale)
            : this(dir, scale, Weather.Fine, DayNight.Morning) {
        }

        public ViewFactor(InterCardinalDirection dir) : this(dir, ZoomScale.x1, Weather.Fine, DayNight.Morning){
        }

        public ViewFactor Clone() {
            return this.MemberwiseClone() as ViewFactor;
        }

        protected InterCardinalDirection viewDir;
        public event EventHandler ViewDirectionChanged;
        /// <summary>
        /// Specifies the world direction which corresponds for upper direction on the view.
        /// </summary>
        public InterCardinalDirection ViewDirection {
            get { return viewDir; }
            set { 
                if(viewDir!=value){
                    viewDir = value; 
                    if(ViewDirectionChanged!=null){
                        ViewDirectionChanged(this, null);
                    }
                }
            }
        }

        protected ZoomScale scale;
        public event EventHandler ScaleChanged;
        /// <summary>
        /// Zoom scale of view
        /// </summary>
        public ZoomScale Scale {
            get { return scale; }
            set {
                if (scale != value) {
                    scale = value;
                    if (ScaleChanged != null) {
                        ScaleChanged(this, null);
                    }
                }
            }        
        }
        /// <summary>
        /// Get scaler for 2D cordinate calculations
        /// </summary>
        public Scaler Scaler { get { return Scaler.Get(this.Scale); } }

        protected Weather weather;
        public event EventHandler WeatherChanged;
        /// <summary>
        /// Get weather type
        /// </summary>
        public Weather Weather {
            get { return weather; }
            set {
                if (weather != value) {
                    weather = value;
                    if (WeatherChanged != null) {
                        WeatherChanged(this, null);
                    }
                }
            }
        }

        protected DayNight daynight;
        public event EventHandler DayNightChanged;
        /// <summary>
        /// Get DayNight
        /// </summary>
        public DayNight DayNight {
            get { return daynight; }
            set {
                if (daynight != value) {
                    daynight = value;
                    if (DayNightChanged != null) {
                        DayNightChanged(this, null);
                    }
                }
            }
        }

        public override bool Equals(object obj) {
            ViewFactor vf = obj as ViewFactor;
            if (vf != null) {
                return (
                    this.ViewDirection == vf.ViewDirection && this.Scale == vf.Scale
                    && this.Weather == vf.Weather && this.DayNight == vf.DayNight);
            } else
                return false;
        }

        public override int GetHashCode()
        {
            int hash = ((short)this.Weather) << 8;
            hash += ((short)this.DayNight) << 8;
            hash += Direction.ToZeroBaseIndex(this.ViewDirection) + this.Scaler.Index;
            return hash;
        }
    }
}
