using System;
using System.Data;
using System.Data.SqlClient;
using System.Threading;
using edu.jhu.Cas.Util;

namespace edu.jhu.Cas.Service{
    public abstract class CJobsDBThread {
        public abstract string ServiceName {get;}
        public abstract string ServiceDescription { get;}
        public abstract int DefaultPanicMinutes { get;}
        public CJobsDBState State;
        public const string QuickQueueNamesQuery = @"
/*
 * names of all non-quick queues
 */
DECLARE @quickQueueNames TABLE(qname varchar(255))

INSERT INTO @quickQueueNames(qname)
select name as qname
from servers s1, (
	--quick queues
	select target, min(queue) as queue from servers
	group by target
) qq
where qq.queue = s1.queue and qq.target = s1.target
";
        protected SqlConnection con = new SqlConnection(SqlFactory.JOBS_STRING);
        Thread thisThread;

        ~CJobsDBThread() { con.Dispose(); }
        
        public void StartThread() {
            initServiceStatus();
            thisThread = new Thread(new ThreadStart(this.Run));
            thisThread.Start();
        }
        public void HaltThread() {
            this.Halt();
            thisThread.Abort();
        }
        protected abstract void Run();
        protected abstract void Halt();

        protected void CycleComplete() {
            string q = @"
select state from servicestatus where [name] = '"+ServiceName+"'";
            try{
                DataSet ds = SqlFactory.select(q);
                State = (CJobsDBState)Enum.Parse(typeof(CJobsDBState), ds.Tables[0].Rows[0][0] as string);
                switch (State) {
                    case CJobsDBState.SUSPENDING:
                        State = CJobsDBState.SUSPENDED;
                        break;
                    case CJobsDBState.WAKING:
                        State = CJobsDBState.RUNNING;
                        break;
                    default: break;
                }
                q = @"update servicestatus set LastCycle = getdate(), State = '" + State + @"' where [name] = '" + ServiceName + @"'";
                SqlFactory.insert(q);
            }catch(Exception e){
                Console.WriteLine(e);
            }
        }
        void initServiceStatus() {
            string q = @"
delete from servicestatus where [Name] = '"+ServiceName+@"'
insert into servicestatus values('" + ServiceName + @"','"+ServiceDescription+"',"+DefaultPanicMinutes
                +",getdate(),'"+CJobsDBState.RUNNING+"')";
            try {
                SqlFactory.insert(q);
            } catch (SqlException se) {
                if (se.Message.IndexOf("PRIMARY KEY") == -1)
                    throw new Exception("Could not initialize service status", se);
            }
        }
        void EnsureConnectionIsOpen(SqlConnection con) {
            switch (con.State) {
                case ConnectionState.Broken:
                    con.Close();
                    con.Open();
                    break;
                case ConnectionState.Closed:
                    con.Open();
                    break;
                case ConnectionState.Connecting:
                    throw new Exception("I didn't think this ever occured");
                    break;
                case ConnectionState.Executing:
                case ConnectionState.Fetching:
                case ConnectionState.Open:
                    return;
            }
        }
        protected DataSet BatchAdminQuery(SqlCommand com) {
            EnsureConnectionIsOpen(com.Connection);
            SqlDataAdapter adap = new SqlDataAdapter(com);
            DataSet rst = new DataSet();
            adap.Fill(rst);
            return rst;
        }
    }
}
