using System;
using System.Collections.Generic;
using System.Linq;
using RalphsDotNet.Data;
using RalphsDotNet.Service.Data.Interface;

namespace RalphsDotNet.Service.Data
{
    public class DataService : IDataService
    {
        private readonly IDataService _proxy;
        private DataManager _manager;

        public DataService (IDataService proxy, ServiceConfiguration configuration)
        {
            this._proxy = proxy;
            this.ServiceConfiguration = configuration;
        }

        public string Id {
            get { return this.ServiceConfiguration.Id; }
        }

        public ServiceConfiguration ServiceConfiguration { get; private set; }

        public DataServiceConfiguration DataServiceConfiguration {
            get { return (DataServiceConfiguration)this.ServiceConfiguration; }
        }

        public bool ActiveTransaction {
            get { return this.GetManager ().ActiveTransaction; }
        }

        public bool ActiveBatchTransaction {
            get { return this.GetManager ().ActiveBatchTransaction; }
        }

        public TR GetRepository<TO, TR> ()
            where TO : IDataObject
            where TR : IDataRepository<TO>
        {
            return this.GetManager ().GetRepository<TO, TR> ();
        }

        public void BeginTransaction ()
        {
            this.GetManager ().BeginTransaction ();
        }

        public void BeginBatchTransaction ()
        {
            this.GetManager ().BeginBatchTransaction ();
        }

        public void CommitTransaction ()
        {
            this.GetManager ().CommitTransaction ();
        }

        public void CommitBatchTransaction ()
        {
            this.GetManager ().CommitBatchTransaction ();
        }

        public void RollbackTransaction ()
        {
            this.GetManager ().RollbackTransaction ();
        }

        public void RollbackBatchTransaction ()
        {
            this.GetManager ().RollbackBatchTransaction ();
        }

        public void SaveOrUpdate (IDataObject obj)
        {
            this.GetManager ().SaveOrUpdate (obj);
        }

        public void BatchSaveOrUpdate (IDataObject obj)
        {
            this.GetManager ().BatchSaveOrUpdate (obj);
        }

        public void SaveOrUpdate (IEnumerable<IDataObject> objs)
        {
            this.GetManager ().SaveOrUpdate (objs);
        }

        public void BatchSaveOrUpdate (IEnumerable<IDataObject> objs)
        {
            this.GetManager ().BatchSaveOrUpdate (objs);
        }

        public void Delete (IDataObject obj)
        {
            this.GetManager ().Delete (obj);
        }

        public void BatchDelete (IDataObject obj)
        {
            this.GetManager ().BatchDelete (obj);
        }

        public void Delete (IEnumerable<IDataObject> objs)
        {
            this.GetManager ().Delete (objs);
        }

        public void BatchDelete (IEnumerable<IDataObject> objs)
        {
            this.GetManager ().BatchDelete (objs);
        }

        public void Reload (IDataObject obj)
        {
            this.GetManager ().Reload (obj);
        }

        public void Reload (IEnumerable<IDataObject> objs)
        {
            this.GetManager ().Reload (objs);
        }

        public IQueryable<T> Get<T> () where T : IDataObject
        {
            return this.GetManager ().Get<T> ();
        }

        public IQueryable<T> BatchGet<T> () where T : IDataObject
        {
            return this.GetManager ().BatchGet<T> ();
        }

        public void TryConnect ()
        {
            this.GetManager ().TryConnect ();
        }

        public void Dispose ()
        {
            if (this._manager != null)
                this._manager.Dispose ();
        }

        private DataManager GetManager ()
        {
            if (this._manager == null) {
                this._manager =
                    Activator.CreateInstance (this.DataServiceConfiguration.DataManagerType) as DataManager;

                if (this._manager != null)
                    this._manager.Initialize (this._proxy);

                if (this._manager == null)
                    throw new ConfigurationException ("error in DataServiceConfig with ID " + this.Id);
            }

            return this._manager;
        }
    }
}