using System;
using System.Web;

namespace StockPortfolio_Web
{
    /// <summary>
    /// Gets stock information by scraping Google Finance pages.
    /// We have used a couple of free web services but they seem to be
    /// taken off-line randomly...
    /// </summary>
    public partial class CurrentStockInfo
    {
        #region ** fields

        private static Random _rand = new Random();

        #endregion
        //public float Open { get; set; }
        //public float Close { get; set; }
        //public float High { get; set; }
        //public float Low { get; set; }
        //public float Volume { get; set; }
        //public float PE { get; set; }
        //public bool Valid { get; set; }
        //public string Symbol { get; set; }
        //public string Name { get; set; }

        //public CurrentStockInfo()
        //{
        //    Name = Symbol = string.Empty;
        //    Valid = false;
        //    Open = float.NaN;
        //    Close = float.NaN;
        //    Low = float.NaN;
        //    High = float.NaN;
        //    Volume = float.NaN;
        //    PE = float.NaN;
        //}

        /// <summary>
        /// Class factory, gets stock information for a given symbol by scraping it 
        /// off the Google Finance page.
        /// </summary>
        /// <param name="symbol"></param>
        /// <returns></returns>
        public static CurrentStockInfo GetStockInfo(Source source, string symbol)
        {
            // create stock into object
            var csi = new CurrentStockInfo();
            csi.Symbol = symbol;

            switch (source)
            {
                case Source.GoogleFinance:
                    // get info from google
                    System.Net.WebClient wc = new System.Net.WebClient();
                    var s = wc.DownloadString(string.Format("http://www.google.com/finance?q={0}", symbol));

                    // handle invalid requests
                    int pos = s.IndexOf("produced no matches");
                    if (pos > -1)
                    {
                        csi.Name = "Symbol not found";
                        return csi;
                    }

                    // get company name from page title
                    pos = s.IndexOf("<title>");
                    if (pos > -1)
                    {
                        pos += 7;
                        int end = s.IndexOf("</title>");
                        if (end > -1)
                        {
                            var cn = s.Substring(pos, end - pos);
                            csi.Name = cn.Split('-')[1].Trim();
                        }
                    }
                    if (csi.Name.IndexOf("Google Finance Search") > -1)
                    {
                        csi.Name = "Symbol not found";
                        return csi;
                    }

                    // scrape info from google page
                    csi.Valid = true;
                    csi.Open = ScrapeValueAfterTag(s, "Open:");
                    csi.Close = ScrapeValueAfterTag(s, "<!-- MARKET DATA -->");
                    csi.High = ScrapeValueAfterTag(s, "High:");
                    csi.Low = ScrapeValueAfterTag(s, "Low:");
                    csi.PE = ScrapeValueAfterTag(s, "P/E:");
                    csi.Volume = ScrapeValueAfterTag(s, "Vol:");

                    break;
                case Source.FlashDB:
                case Source.Static:
                default:
                    csi.Valid = true;
                    float value = 20.33f;
                    csi.Open = value * (float)(_rand.NextDouble() + 0.5);
                    csi.Close = csi.Open * (float)(_rand.NextDouble() + 0.5);
                    csi.High = value + 0.22f;
                    csi.Low = value - 0.22f;
                    csi.PE = value / 2;
                    csi.Volume = 0;
                    break;
            }
            // done
            return csi;
        }
        static float ScrapeValueAfterTag(string s, string tag)
        {
            float value = float.NaN;

            int pos = s.IndexOf(tag);
            if (pos > -1)
            {
                int nest = 0;
                for (int index = pos; index < s.Length && float.IsNaN(value); index++)
                {
                    var c = s[index];
                    switch (c)
                    {
                        case '<':
                            nest++;
                            break;
                        case '>':
                            nest--;
                            break;
                        default:
                            if (nest == 0 && char.IsDigit(c))
                            {
                                int start = index;
                                for (int end = start + 1; end < s.Length; end++)
                                {
                                    if (!char.IsDigit(s[end]) && s[end] != '.' && s[end] != ',')
                                    {
                                        value = float.Parse(
                                            s.Substring(start, end - start),
                                            System.Globalization.NumberStyles.Any,
                                            System.Globalization.CultureInfo.InvariantCulture);

                                        // 3.6M => 3.6 million
                                        if (s[end] == 'M')
                                        {
                                            value *= 1000000;
                                        }
                                        break;
                                    }
                                }
                            }
                            break;
                    }
                }
            }
            return value;
        }
    }
}
