using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using ChaKi.Entity.Corpora;
using ChaKi.Entity;
using System.Data;

namespace ChaKi.Service.Database
{
    /// <summary>
    /// Session, Transaction管理を行うクラス
    /// ChaKi EntityのProject, Userも同時に保持し、DBへの変更が
    /// どのProject, Userによって行われているかを知っている.
    /// </summary>
    public class OpContext : IDisposable
    {
       protected OpContext()
        {
            this.Session = null;
            this.Trans = null;
            this.Sen = null;
            this.Proj = null;
            this.User = null;
            this.Name = string.Empty;
        }

        public string Name { get; set; }
        public Project Proj { get; set; }
        public User User { get; set; }
        public ISession Session { get; set; }
        public Sentence Sen { get; set; }
        public ITransaction Trans { get; set; }

        public DBService DBService { get; private set; }

        public bool IsTransactionActive()
        {
            return (this.Trans != null && this.Session != null);
        }

        public static OpContext Create(DBParameter param, UnlockRequestCallback callback, Type requestingService)
        {
            // Corpus(DB)の種類に合わせてConfigurationをセットアップする
            OpContext ctx = new OpContext();
            ctx.DBService = DBService.Create(param, callback, requestingService);
            ctx.Session = ctx.DBService.OpenSession();
            ctx.Trans = ctx.Session.BeginTransaction();
            return ctx;
        }

        public void SaveOrUpdate(object obj)
        {
            this.Session.SaveOrUpdate(obj);
        }

        public void Save(object obj)
        {
            this.Session.Save(obj);
        }

        public void Delete(object obj)
        {
            this.Session.Delete(obj);
        }

        public void Flush()
        {
            this.Session.Flush();
        }

        public void Dispose()
        {
            if (IsTransactionActive())
            {
                this.Trans.Rollback();
            }
            try
            {
                if (this.Trans != null)
                {
                    this.Trans.Dispose();
                }
                if (this.Session != null)
                {
                    this.Session.Dispose();
                }
            }
            finally
            {
                this.Trans = null;
                this.Session = null;
            }
        }
    }
}
