using System.Collections;
using System.Data;
using System.Data.Common;
using ChaKi.Entity.Corpora;
using ChaKi.Entity.Kwic;
using ChaKi.Entity.Search;
using NHibernate;
using System.Collections.Generic;
using System;

namespace ChaKi.Service.Search
{
    public class SentenceListService : SearchServiceBase
    {
        private KwicList m_Model;

        public SentenceListService(SearchHistory hist, SearchHistory parent)
            : base(hist, parent)
        {
            m_Model = hist.KwicList;
        }

        /// <summary>
        /// コーパスごとのSentenceList本体
        /// </summary>
        /// <param name="c"></param>
        protected override void ExecuteSearchSession(Corpus c)
        {
            SearchConditions cond = m_CondSeq.Last;  //TODO: 絞り込み等ではCondSeqを順次検索しなければならない

            // Sentence Listのクエリを生成する
            string qstr = QueryBuilder.Instance.BuildSentenceListQuery(c, cond); 
            IQuery query = m_Session.CreateQuery(qstr);
            IList<Sentence> queryResult = query.List<Sentence>();
            int totalCount = queryResult.Count;
            IEnumerable<Sentence> filteredResult = (cond.FilterCond.AllEnabled) ?
                cond.FilterCond.ResultsetFilter.CreateEnumerable<Sentence>(queryResult) : queryResult;

            // ここまでで検索は終了。

            // 検索されたSentenceに対して、文内容をKwicに変換・出力する
            int n = 0;
            m_Progress.SetRange(totalCount);
            foreach (Sentence sen in filteredResult)
            {
                KwicItem ki = new KwicItem(c, sen.ParentDoc, sen.ID, sen.StartChar, sen.EndChar, sen.Pos);

                // sen.Words 以下のアクセスは、Hibernateではなく直接SQLで行う（Maxパフォーマンスのため）
                List<int> lexids = new List<int>();
                IDbConnection conn = m_Session.Connection;
                IDbCommand cmd = conn.CreateCommand();
                //!SQL
                cmd.CommandText = string.Format("SELECT lexeme_id from word where sentence_id={0} ORDER BY position", sen.ID);
                IDataReader rdr = cmd.ExecuteReader();
                while (rdr.Read())
                {
                    lexids.Add((int)rdr[0]);
                }
                rdr.Close();

                foreach (int lexid in lexids)
                {
                    // CorpusのLexiconへ問い合わせ＆追加
                    Lexeme lex;
                    if (!c.Lex.TryGetLexeme(lexid, out lex))
                    {
                        //!SQL
                        ISQLQuery sq = m_Session.CreateSQLQuery(string.Format("SELECT * from lexeme where id={0}", lexid))
                            .AddEntity(typeof(Lexeme));
                        IList<Lexeme> sqres = sq.List<Lexeme>();
                        if (sqres.Count != 1)
                        {
                            throw new Exception("Error Querying Lexeme");
                        }
                        lex = sqres[0];
                        c.Lex.Add(lex);
                    }
                    ki.Right.AddLexeme(lex, 0);
                }
                m_Model.AddKwicItem(ki);
                m_Progress.Increment();
                n++;
            }
        }
    }
}
