using System;
using System.Collections.Generic;
using System.Text;
using nft.framework.drawing;
using nft.core.geometry;
using System.Drawing;
using System.Diagnostics;

namespace nft.impl.view_old {

    public class ViewObjectList {
        protected List<ViewObject> viewObjs;
        protected Rect3DV range;
        protected bool dirty;

        public ViewObjectList()
            : this(Rect3DV.NULL) {}

        public ViewObjectList(Rect3DV clip) {
            this.viewObjs = new List<ViewObject>();
            this.range = clip;
            this.dirty = false;
        }

        public Rect3DV ClipArea {
            get{ return range; }
            set {
                if (!range.Equals(value)) {
                    range = value;
                    applyClip();
                }
            }
        }

        public int ObjectCount {
            get { return viewObjs.Count; }
        }

        public ViewObject this[int index] {
            get { return viewObjs[index]; }
        }

        public bool Sorted { get { return !dirty; } }

        public void Sort() {
            if (dirty) {
                viewObjs.Sort();
                dirty = false;
            }
        }

        public IEnumerator<ViewObject> GetEnumerator() {
            return viewObjs.GetEnumerator();
        }

        protected void applyClip() {
            int n = viewObjs.Count - 1;
            int c = 0;
            for(int i=n; n>=0; i--){
                ViewObject o = viewObjs[i];
                Rect3DV r = o.Bounds;
                if (!ClipArea.IntersectWith(r)) {
                    viewObjs.RemoveAt(i);
                    c++;
                }
            }
            Debug.WriteLine(string.Format("{0} items are eliminated.",c),"ViewObjectList");
        }

        public void Clear() {
            viewObjs.Clear();
            dirty = false;
        }

        public void AddObject(ITextureOld txt, Rect3DV rect) {
            ViewObject vo = new ViewObject(txt, rect);
            viewObjs.Add(vo);
            dirty = true;
        }

        public void RemoveObject(ViewObject vo){
            dirty = viewObjs.Remove(vo);
        }

        public void RemoveAt(int idx) {
            viewObjs.RemoveAt(idx);
            dirty = true;
        }

    }

    public class ViewObject : IComparable<ViewObject> {
        private readonly ITextureOld texture;
        private readonly Rect3DV rect;
        private ViewObject next;

        internal ViewObject(ITextureOld t, Rect3DV bounds) {
            this.texture = t;
            this.rect = bounds;
            this.next = null;
        }

        public Rect3DV Bounds { get { return rect; } }

        //public ISprite Sprite { get { return sprite; } }
        public ITextureOld Texture { get { return texture; } }

        public ViewObject NextObject {
            get { return next; }
            set { next = value; }
        }                 

        #region IComparable<ViewObject> メンバ

        public int CompareTo(ViewObject other) {
            if (this.rect.VY2 <= other.rect.VY) {
                return -1;
            }
            if (this.rect.VX2 <= other.rect.VX) {
                return -1;
            }
            if (this.rect.VY >= other.rect.VY2) {
                return 1;
            }
            if (this.rect.VX >= other.rect.VX2) {
                return 1;
            }
            int v = other.rect.VZ2 - this.rect.VZ2;
            if (v != 0) {
                return v;
            } else {
                v = this.rect.VY - other.rect.VY;
                if (v != 0) {
                    return v;
                }
                return this.rect.VX - other.rect.VX;
            }
        }

        #endregion
    }
}
