using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using edu.jhu.Cas.Util;
using edu.jhu.Cas.Users;
using net.ivoa.data;

namespace edu.jhu.Cas.Web {
	public class Admin : System.Web.UI.Page {
		protected DataSet  ds,ods,users,groups,group;
        protected DataGrid dg, og;
		protected bool loggedin;
		protected long wsid;
		protected string lmessage;
		protected System.Web.UI.WebControls.Button loginButton;
		public  bool isadmin;
		protected string userid,groupName;
		protected Button deleteuserbutton;
		protected User currentUser;
		protected TextBox PrivsBox,MaxSizeBox,GPrivsBox;
		protected System.Web.UI.WebControls.TextBox NewPassBox;
		protected System.Web.UI.WebControls.Button Button1;
		
		protected void Login(object sender, System.EventArgs E){
			long theirID = (new CasUsers()).GetWebServiceId(edu.jhu.Cas.Util.ID.SERVICE_ID,userid.Trim());	
			Session["USER"]=theirID;
			Session["USERID"]=userid;
			Response.Redirect("SubmitJob.aspx");
		}
		protected void DeleteUser(object sender, System.EventArgs E){
			if(userid== null || userid.Length< 1){lmessage = "Enter a user first."; return;}
			CasUsers cUsers = new CasUsers();
			long theirwsid = cUsers.GetWebServiceId(edu.jhu.Cas.Util.ID.SERVICE_ID,userid.Trim());
			try{
				cUsers.DeleteAccount(edu.jhu.Cas.Util.ID.SERVICE_ID,theirwsid);
				lmessage = "Account "+userid+" succesfully deleted.";
			}catch(Exception e){
				lmessage = e.ToString();
			}
		}
		protected void ApplyUserChanges(object sender, System.EventArgs E){
			CasUsers cusers = new CasUsers();
			long id = cusers.GetWebServiceId(edu.jhu.Cas.Util.ID.SERVICE_ID,userid.Trim());	
			if (NewPassBox.Text !=null && NewPassBox.Text.Length >0){
				currentUser.PWEncrypted=NewPassBox.Text;
			} 
			else {
                // update account wil leave the password as is if this is null
				// of course this meanse you can never SET a NULL password but if you never set it
				// you may have a NULL password
				currentUser.PWEncrypted=null;
			}
			currentUser.Privileges = PrivsBox.Text;
			cusers.ChangeDBMaxSize(edu.jhu.Cas.Util.ID.SERVICE_ID,id,int.Parse(MaxSizeBox.Text));
			cusers.UpdateAccount(id,currentUser);
			lmessage="Changes to "+userid+" have been made.";
		}
        protected void ApplyGroupChanges(object sender, System.EventArgs E) {
            if (GPrivsBox.Text == "" || GPrivsBox.Text == null) {
                lmessage = "No changes made";
                return;
            }
            try {
                SqlFactory.nonselect_param(UpdateGroupQry, UpdateGroupQryParams, UpdateGroupQryTypes,
                           new int[2] { 200, 64 }, new object[2] { GPrivsBox.Text, (long)group.Tables[0].Rows[0]["gid"] });
                lmessage = "Updated " + groupName;
            }
            catch (Exception e) {
                lmessage = e.Message;
            }
        }
		protected bool isloggedin(string u) {
			if(u == null)return false;
			foreach(object o in Global.users)
				if(o != null && o.ToString().Trim().CompareTo(u.Trim()) == 0)
					return true;
			return false;
		}
		private void Page_Load(object sender, System.EventArgs E) {}		
		override protected void OnInit(EventArgs e) {
			InitializeComponent();
			base.OnInit(e);
		}
        private DataSet GetActiveQueues() {
            DataSet ds = SqlFactory.select(ActiveQueuesQuery);
            string last = "", thisRow = ""; 
            bool doAlt = false;
            for (int i = 0; i < ds.Tables[0].Rows.Count;i++ ) {
                ds.Tables[0].Rows[i]["Target"] = ds.Tables[0].Rows[i]["Target"].ToString().ToUpper();
                thisRow = ds.Tables[0].Rows[i]["Target"].ToString() + ds.Tables[0].Rows[i]["Queue"].ToString();
                if (last == "") {
                    last = thisRow;
                    continue;
                }
                if (last != thisRow) {
                    doAlt = !doAlt;
                    last = thisRow;
                }
                if (doAlt)
                    for (int j = 0; j < ds.Tables[0].Columns.Count; j++) {
                        if (ds.Tables[0].Columns[j].ColumnName == "jobid") continue;
                        if(ds.Tables[0].Rows[i][j] is DBNull)
                            ds.Tables[0].Rows[i][j] = "&nbsp;";
                        ds.Tables[0].Rows[i][j] = "<div class=\"alt\">" + ds.Tables[0].Rows[i][j] + "</div>";
                    }
            }
            return ds;
        }
        private DataSet GetActiveOutput() {return SqlFactory.select(ActiveOutputQuery);}
		private void InitializeComponent() {    
			this.Load += new System.EventHandler(this.Page_Load);
			WebUtils.CheckLoggedIn(Session,Response,Request,true);
			lmessage = Request.Params["lmessage"];
			loggedin = Session["USER"] != null;  
			
			if (loggedin) 
				wsid = (long)Session["USER"];
			try{
				(new CasUsers()).HasPrivilege(wsid,PRIVS.SIGHT);
				isadmin=true;
				Session["MENU"] = MENU.ADMIN;
			}catch{
				isadmin = false;
				Session["MENU"] = MENU.QUEUE;
			}
			ds = GetActiveQueues();
			dg.DataSource = ds.Tables[0];
			dg.DataBind();

            ods = GetActiveOutput();
            og.DataSource = ods.Tables[0];
			og.DataBind();
			lmessage = "System Time: "+DateTime.Now.ToString();
            if (isadmin) {
                deleteuserbutton.Attributes.Add("onclick", "return confirm_delete('" + userid + "');");
                userid = Request.Params["userid"];
                groupName = Request.Params["groupName"];
                users = SqlFactory.select(usersQry);              
                groups = SqlFactory.select(groupsQry);
                if (userid != null) {
                    try {
                        currentUser = (new CasUsers()).FindUser(
                            edu.jhu.Cas.Util.ID.SERVICE_ID, "userid = '" + userid + "'")[0];
                    }
                    catch {
                        userid = null;
                        lmessage = "UserID '" + userid + "' not found";
                        return;
                    }
                    PrivsBox.Text = currentUser.Privileges;
                    MaxSizeBox.Text = currentUser.MyDBMaxSize.ToString();
                }
                else if (groupName != null) {
                    group = SqlFactory.select_param(groupQry, groupQryParams, groupQryTypes,
                        new int[1] { 200 }, new object[1] { groupName });
                    GPrivsBox.Text = group.Tables[0].Rows[0]["privs"] as string;
                }
                initServiceState();
            }			
		}
        void initServiceState() {
            string service = Request.Params["service"];
            string sstate = Request.Params["sstate"];
            if (service != null && sstate != null) {
                DataSet ds = SqlFactory.select("select state from servicestatus where [name] ='"+service+"'");
                CJobsDBState currentState = (CJobsDBState)Enum.Parse(typeof(CJobsDBState), ds.Tables[0].Rows[0][0] as string);
                CJobsDBState nextState = (CJobsDBState)Enum.Parse(typeof(CJobsDBState), sstate);
                if((currentState == CJobsDBState.RUNNING && nextState == CJobsDBState.SUSPENDING) ||
                    (currentState == CJobsDBState.SUSPENDED && nextState == CJobsDBState.WAKING))
                    SqlFactory.insert("update servicestatus set state = '" + sstate + "' where [name] = '" + service + "'");
            }
            DataSet sds = SqlFactory.select("select * from servicestatus");
            sds.Tables[0].Columns.Add("action", typeof(string));
            foreach (DataRow dr in sds.Tables[0].Rows) {
                CJobsDBState state = (CJobsDBState)Enum.Parse(typeof(CJobsDBState), dr["state"] as string);
                string onclick = "onclick=\"window.open('admin.aspx?service="+dr["Name"]+"&sstate=";
                switch (state) {
                    case CJobsDBState.RUNNING:
                        dr["action"] = "<input type=\"button\" value=\"Suspend\" onclick=\""+
                            "window.open('admin.aspx?service="+dr["Name"]+"&sstate="+CJobsDBState.SUSPENDING+"','_top','');\"/>";
                        break;
                    case CJobsDBState.SUSPENDED:
                        dr["action"] = "<input type=\"button\" value=\"Wake\" onclick=\"" +
                            "window.open('admin.aspx?service=" + dr["Name"] + "&sstate=" + CJobsDBState.WAKING+ "','_top','');\"/>";
                        break;
                    case CJobsDBState.SUSPENDING:
                        dr["action"] = "Busy...";
                        break;
                    case CJobsDBState.WAKING:
                        dr["action"] = "Busy...";
                        break;
                    default: break;
                }
            }
            DataSetWrapper sdsw = new DataSetWrapper(sds);
            sdsws = WrapperFactory.Wrapper2HTML(sdsw,SYSTEM.MAX_HTML_DATA_CHARS);
        }
        protected string sdsws;
        private const string usersQry = @"
select distinct userid, name 
from users
where privileges is null
or (
	privileges not like '%system%' 
	and privileges not like '%admin%'
)
order by name asc";
        private const string groupsQry = @"select name from groups";       
        private const string groupQry = @"
select g.name as gname, g.gid, g.description, g.privs, g.owner, u.userid, u.email, u.name as oname
from groups g, users u
where u.webservicesid = g.owner
and g.name = @name";
        private static string[] groupQryParams = new string[1] { "@name" };
        private static SqlDbType[] groupQryTypes = new SqlDbType[1] { SqlDbType.VarChar };
        private const string ActiveQueuesQuery = @"
select j.target as Target, cast(j.estimate as varchar) as queue, u.userid, 
    cast(j.timesubmit as varchar) as timesubmit, cast(j.timestart as varchar) as timestart, 
    s.html, cast(j.jobid as varchar) as jobid
from jobs j, users u, status s, (
	select distinct target,queue from servers s1
	where s1.name not in
	(
		select name 
		from servers s, (
			select target, min(queue) as queue
			from servers
			group by target
		) a
		where a.target = s.target and s.queue = a.queue
	)
) b
where j.target = b.target and j.estimate = b.queue
    and (j.status = 0 or j.status = 1 or j.status = 2)
    and u.webservicesid = j.webservicesid
    and j.status = s.status
    and j.outputtype like '%QUERY%%' 
order by j.target, j.status desc, j.estimate, j.timesubmit asc";
        public const string ActiveOutputQuery = @"
select u.userid,j.timesubmit,j.timestart, j.outputtype, s.html,j.jobid
from jobs j, users u, status s
where (j.status = 0 or j.status = 1 or j.status = 2) 
and u.webservicesid = j.webservicesid 
and j.outputtype not like '%QUERY%%' 
and j.status = s.status
order by j.status desc";
        public const string UpdateGroupQry = @"
update groups
set privs = @privs
where gid = @gid";
        private static string[] UpdateGroupQryParams= new string[2] { "@privs","@gid" };
        private static SqlDbType[] UpdateGroupQryTypes = new SqlDbType[2] { SqlDbType.VarChar, SqlDbType.BigInt };
	}
}
