using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using edu.jhu.Cas.Web;
using edu.jhu.Cas.Users;
using RestApi.Models;
using edu.jhu.Cas.Jobs;
using RestApi.Exceptions;
using SciServer.Logging;
using System.Web;
using Newtonsoft.Json;

namespace RestApi.Controllers
{
    public class JobsController : ApiController
    {
        [ExceptionHandle]
        public HttpResponseMessage Delete(int id)
        {
            Logger log = (HttpContext.Current.ApplicationInstance as MvcApplication).Log;

            IEnumerable<string> values;
            string userid = null;

            if (ControllerContext.Request.Headers.TryGetValues("X-Auth-Token", out values))
            {
                long? wsid;

                try
                {
                    string token = values.First();
                    var userAccess = Keystone.Authenticate(token);
                    userid = userAccess.User.Id;

                    wsid = Keystone.GetWebServicesId(userAccess.User.Id);
                    if (wsid == null) throw new Exception("CasJobs user with the given Keystone ID does not exist");
                }
                catch (Exception ex)
                {
                    AuthException ex2 = new AuthException("Authentication failed", ex);
                    ex2.Data["UserId"] = userid;
                    throw ex2;
                }

                JobInfo job;
                try
                {
                    job = JobInfo.FromId(id, wsid.Value);
                }
                catch (Exception ex)
                {
                    Exception ex2 = new Exception("Could not get job info", ex);
                    ex2.Data["UserId"] = userid;
                    throw ex2;
                }

                if (job != null)
                {
                    CasJobs cj = new CasJobs();
                    cj.CancelJob(wsid.Value, job.JobID);
                    Message message = log.CreateInfoMessage("Job " + id + " cancelled");
                    message.UserId = userid;
                    log.SendMessage(message);
                    return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, job, "application/json");
                }
                else
                {
                    NotFoundException ex2 = new NotFoundException("Job " + id + " not found");
                    ex2.Data["UserId"] = userid;
                    throw ex2;
                }
            }
            else
            {
                throw new AuthException("User not authenticated");
            }
        }

        [ExceptionHandle]
        public HttpResponseMessage Get(int id)
        {
            Logger log = (HttpContext.Current.ApplicationInstance as MvcApplication).Log;

            IEnumerable<string> values;
            string userid = null;

            if (ControllerContext.Request.Headers.TryGetValues("X-Auth-Token", out values))
            {
                long? wsid;

                try
                {
                    string token = values.First();
                    var userAccess = Keystone.Authenticate(token);
                    userid = userAccess.User.Id;
                    wsid = Keystone.GetWebServicesId(userAccess.User.Id);
                    if (wsid == null) throw new Exception("CasJobs user with the given Keystone ID does not exist");
                }
                catch (Exception ex)
                {
                    AuthException ex2 = new AuthException("Authentication failed", ex);
                    ex2.Data["UserId"] = userid;
                    throw ex2;
                }

                JobInfo job;
                try
                {
                    job = JobInfo.FromId(id, wsid.Value);
                }
                catch (Exception ex)
                {
                    Exception ex2 = new Exception("Could not get job info", ex);
                    ex2.Data["UserId"] = userid;
                    throw ex2;
                }

                if (job != null)
                {
                    return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, job, "application/json");
                }
                else
                {
                    NotFoundException ex2 = new NotFoundException("Job " + id + " not found");
                    ex2.Data["UserId"] = userid;
                    throw ex2;
                }
            }
            else
            {
                throw new AuthException("User not authenticated");
            }
        }

        [HttpPut]
        [ExceptionHandle]
        public HttpResponseMessage CreateJob(string context_id, [FromBody]JobRequest req)
        {
            Logger log = (HttpContext.Current.ApplicationInstance as MvcApplication).Log;
            IEnumerable<string> values;
            string userid = null;

            if (ControllerContext.Request.Headers.TryGetValues("X-Auth-Token", out values))
            {
                long? wsid;

                try
                {
                    string token = values.First();
                    var userAccess = Keystone.Authenticate(token);
                    userid = userAccess.User.Id;
                    wsid = Keystone.GetWebServicesId(userAccess.User.Id);
                    if (wsid == null) throw new Exception("CasJobs user with the given Keystone ID does not exist");
                }
                catch (Exception ex)
                {
                    AuthException ex2 = new AuthException("Authentication failed", ex);
                    ex2.Data["UserId"] = userid;
                    throw ex2;
                }

                long jobid;
                try
                {
                    Message message = log.CreateCustomMessage("UNDEFINED",JsonConvert.SerializeObject(req));
                    message.UserId = userid;
                    log.SendMessage(message);

                    string query = req.Query;
                    if (req.CreateTable)
                    {
                        query = WsUtil.AddIntoClause(query, wsid.Value, req.TableName);
                    }

                    CasJobs cj = new CasJobs();
                    jobid = cj.SubmitJob(wsid.Value, query, context_id, req.TaskName, req.Estimate, 0);

                }
                catch (Exception ex)
                {
                    Exception ex2 = new Exception("Could not create job", ex);
                    ex2.Data["UserId"] = userid;
                    throw ex2;
                }

                Message msg = log.CreateInfoMessage("Job " + jobid + " created");
                msg.UserId = userid;
                log.SendMessage(msg);

                return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, jobid, "application/json");
            }
            else
            {
                throw new AuthException("User not authenticated");
            }
        }
    }
}
