// Chattr - Twitter client on .NET
//
// Copyright (c) 2007 Katsuhiko Ichinose <ichi@users.sourceforge.jp>
//
// Chattr is Free Software released under GNU General Public License.
//
// $Id: twitte.rb 61 2007-07-17 18:11:25Z ichi $

using System;
using System.Collections.Generic;
using System.Text;

using System.Collections;
using System.Text.RegularExpressions;

namespace Chattr
{
    class StatusParser
    {
        private const string REGEX_USER_NAME = @"^(@)([0-9A-Za-z_]+)(.*)$";
        private const string REGEX_USER_CONT = @"^(.*?[^0-9A-Za-z_]@)([0-9A-Za-z_]+)(.*)$";

        private ArrayList m_Users = new ArrayList();
        private ArrayList m_URLs = new ArrayList();
        private ArrayList m_Locations = new ArrayList();

        public StatusParser(string status)
        {
            string jpn = @"℀-➾　-㏾一-龥豈-鶴！-￬";
            string anc = @"0-9a-zA-Z\-_\.!~\*'\(\)/\?&=,:%@";
            string lst = @"0-9a-zA-Z\-_\.!~\*'/";
            Regex rHttp = new Regex(@"^(.*?)((?:http|https)://[" + jpn + anc + "]*[" + lst + "])(.*)$");
            Regex rLoc = new Regex(@"^(.*?)(?:L|l):([^ ]+)(.*)$");
            Regex rUserName = new Regex(REGEX_USER_NAME);
            Regex rUserCont = new Regex(REGEX_USER_CONT);
            foreach (string text in status.Split('\n'))
            {
                string txt = text;
                while (txt != "")
                {
                    Match m = rHttp.Match(txt);
                    if (m.Success)
                    {
                        ParseUserName(m.Groups[1].Value);
                        AddURL(m.Groups[2].Value);
                        txt = m.Groups[3].Value;
                    }
                    else
                    {
                        m = rLoc.Match(txt);
                        if (m.Success)
                        {
                            ParseUserName(m.Groups[1].Value);
                            AddLocation(m.Groups[2].Value);
                            txt = m.Groups[3].Value;
                        }
                        else
                        {
                            ParseUserName(txt);
                            txt = "";
                        }
                    }
                }
            }
        }

        private void ParseUserName(string status)
        {
            Regex rUserName = new Regex(REGEX_USER_NAME);
            Regex rUserCont = new Regex(REGEX_USER_CONT);
            Match mUserName = rUserName.Match(status);
            Match mUserCont = rUserCont.Match(status);
            while (mUserName.Success || mUserCont.Success)
            {
                if (mUserName.Success)
                {
                    AddUser(mUserName.Groups[2].Value);
                    status = mUserName.Groups[3].Value;
                }
                else if (mUserCont.Success)
                {
                    AddUser(mUserCont.Groups[2].Value);
                    status = mUserCont.Groups[3].Value;
                }
                mUserName = rUserName.Match(status);
                mUserCont = rUserCont.Match(status);
            }
        }

        private void AddUser(string user)
        {
            m_Users.Add(user);
        }

        private void AddURL(string url)
        {
            m_URLs.Add(url);
        }

        private void AddLocation(string location)
        {
            m_Locations.Add(location);
        }

        public string[] Users
        {
            get
            {
                int cnt = m_Users.Count;
                if (cnt == 0)
                {
                    return null;
                }
                string[] users = new string[cnt];
                for (int i = 0; i < cnt; i++)
                {
                    users[i] = (string)m_Users[i];
                }
                return users;
            }
        }

        public string[] URLs
        {
            get
            {
                int cnt = m_URLs.Count;
                if (cnt == 0)
                {
                    return null;
                }
                string[] URLs = new string[cnt];
                for (int i = 0; i < cnt; i++)
                {
                    URLs[i] = (string)m_URLs[i];
                }
                return URLs;
            }
        }

        public string[] Locations
        {
            get
            {
                int cnt = m_Locations.Count;
                if (cnt == 0)
                {
                    return null;
                }
                string[] locations = new string[cnt];
                for (int i = 0; i < cnt; i++)
                {
                    locations[i] = (string)m_Locations[i];
                }
                return locations;
            }
        }
    }
}
