// Copyright (C) 2008 panacoran <panacoran@users.sourceforge.jp>
// 
// This program is part of Protra.
//
// Protra is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
// 
// $Id: BasicBuiltins.cs 374 2010-05-01 02:43:36Z panacoran $

using System;
using System.Collections.Generic;
using Protra.Lib.Data;

namespace Protra.Lib.Lang
{
    /// <summary>
    /// 基本的な組み込み関数を実行するクラス。実行に必要なコンテキストも保持する。
    /// </summary>
    public class BasicBuiltins : MathBuiltins
    {
        /// <summary>
        /// 実行対象の価格データを取得または設定する。
        /// </summary>
        public List<Price> Prices { set; get; }
        /// <summary>
        /// インデックスを設定または取得する。
        /// </summary>
        public int Index { get; set; }
        /// <summary>
        /// 右端のインデックスを取得または設定する。
        /// </summary>
        public int RightIndex { get; set; }
        /// <summary>
        /// 銘柄データを取得する。
        /// </summary>
        public Brand Brand
        {
            get
            {
                return GlobalEnv.BrandData[Prices[0].Code];
            }
        }

        /// <summary>
        /// 組み込み関数を実行する。
        /// </summary>
        /// <param name="name">名前</param>
        /// <param name="args">引数</param>
        /// <param name="at">atパラメータ</param>
        /// <returns></returns>
        public override Value Invoke(string name, Value[] args, int at)
        {
            if (args.Length != 0)
                return base.Invoke(name, args, at);
            switch (name)
            {
                case "Index":
                    return new Value(Index + at);
                case "RightIndex":
                    return new Value(RightIndex);
                case "Code":
                    return new Value(Brand.Code);
                case "Market":
                    return new Value(Brand.Market);
                case "Unit":
                    return new Value(Brand.Unit);
            }
            if (Index + at < 0 || Index + at >= Prices.Count)
                return null;
            var price = Prices[Index + at];
            switch (name)
            {
                case "Year":
                    return new Value(price.Date.Year);
                case "Month":
                    return new Value(price.Date.Month);
                case "Day":
                    return new Value(price.Date.Day);
                case "DayOfWeek":
                    return new Value((int)price.Date.DayOfWeek);
                case "Open":
                    return new Value(price.Open);
                case "High":
                    return new Value(price.High);
                case "Low":
                    return new Value(price.Low);
                case "Close":
                    return new Value(price.Close);
                case "Volume":
                    return new Value(price.Volume);
            }
            return base.Invoke(name, args, at);
        }
    }
}
