/*
 * VsqEventList.cs
 * Copyright (c) 2008-2009 kbinani
 *
 * This file is part of Boare.Lib.Vsq.
 *
 * Boare.Lib.Vsq is free software; you can redistribute it and/or
 * modify it under the terms of the BSD License.
 *
 * Boare.Lib.Vsq is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
using System;
using System.Collections.Generic;

namespace Boare.Lib.Vsq {

    /// <summary>
    /// 固有ID付きのVsqEventのリストを取り扱う
    /// </summary>
    [Serializable]
    public class VsqEventList {
        public List<VsqEvent> Events;
        private List<int> m_ids;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public VsqEventList() {
            Events = new List<VsqEvent>();
            m_ids = new List<int>();
        }

        public void sort() {
            lock ( this ) {
                Events.Sort();
                for ( int i = 0; i < Events.Count; i++ ) {
                    m_ids[i] = Events[i].InternalID;
                }
            }
        }

        public void clear() {
            Events.Clear();
            m_ids.Clear();
        }

        public Iterator iterator() {
            updateIDList();
            return new ListIterator<VsqEvent>( Events );
        }

        public void add( VsqEvent item ) {
            updateIDList();
            int new_id = getNextId( 0 );
            item.InternalID = new_id;
            Events.Add( item );
            m_ids.Add( new_id );
            Events.Sort();
            for ( int i = 0; i < Events.Count; i++ ) {
                m_ids[i] = Events[i].InternalID;
            }
        }

        public void removeAt( int index ) {
            updateIDList();
            Events.RemoveAt( index );
            m_ids.RemoveAt( index );
        }

        private int getNextId( int next ) {
            updateIDList();
            int index = -1;
            List<int> current = new List<int>( m_ids );
            int nfound = 0;
            while ( true ) {
                index++;
                if ( !current.Contains( index ) ) {
                    nfound++;
                    if ( nfound == next + 1 ) {
                        return index;
                    } else {
                        current.Add( index );
                    }
                }
            }
        }

        public int getCount() {
            return Events.Count;
        }

        public VsqEvent getElement( int index ) {
            return Events[index];
        }

        public void setElement( int index, VsqEvent value ) {
            Events[index] = value;
        }

        public void updateIDList() {
            if ( m_ids.Count != Events.Count ) {
                m_ids.Clear();
                for ( int i = 0; i < Events.Count; i++ ) {
                    m_ids.Add( Events[i].InternalID );
                }
            }
        }
    }

}
