﻿namespace HomeworkBCL
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;

    public class MyStack<T> : IStack<T>, IEnumerator, IEnumerable
    {
        private List<T> list;
        private static Int32 maxStackSize = 10;

        public MyStack()
        {
            list = new List<T>();
        }

        #region Basic Method
        public void Push(T t)
        {
            if (IsFull())
            {
                String message = String.Format("\n\n***** Max size of MyStack<T> is {0} *****\n", maxStackSize);
                throw new StackOverflowException(message);
            }
            list.Add(t);
        }

        public T Pop()
        {
            if (IsEmpty())
            {
                return default(T);
            }
            T t = list[list.Count - 1];
            list.RemoveAt(list.Count - 1);
            return t;
        }

        public T Peek()
        {
            return list[list.Count - 1];
        }

        public void Empty()
        {
            list.Clear();
        }

        public Boolean IsFull()
        {
            if (list.Count >= MyStack<T>.maxStackSize)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public Boolean IsEmpty()
        {
            if (list.Count == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public Int32 Count()
        {
            return list.Count;
        }

        public override string ToString()
        {
            StringBuilder result = new StringBuilder();
            for (int i = list.Count - 1; i >= 0; i--)
            {
                result.Append(list[i].ToString());
                result.Append("\n");
            }
            return result.ToString();
        }
        /*
                public IEnumerator GetEnumerator()
                {
                    Int32 size = list.Count;
                    for (int i = 0; i < size; i++)
                    {
                        //if the list changed, then throw exception
                        if (size != list.Count)
                        {
                            throw new InvalidOperationException();
                        }
                        yield return list[i];
                    }

                    //A other way to do this
                    //foreach(T tmp in list)
                    //{
                    //    yield return tmp;
                    //}
            
                }
        */
        #endregion

        #region IEnumerator Implement
        private Int32 index = -1;
        private Int32 tmpStackSize;

        IEnumerator IEnumerable.GetEnumerator()
        {
            return (IEnumerator)GetEnumerator();
        }

        public MyStack<T> GetEnumerator()
        {
            tmpStackSize = this.list.Count;
            return this;
        }

        Object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }

        public bool MoveNext()
        {
            index++;
            if (tmpStackSize != list.Count)
            {
                String message = String.Format("\n\n****Cant change the collection in foreach statement.****\n");
                throw new InvalidOperationException(message);
            }
            return (index < tmpStackSize);
        }

        public void Reset()
        {
            index = -1;
        }

        public T Current
        {
            get
            {
                try
                {
                    return list[index];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
        #endregion
    }
}
