using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Configuration;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using RestApi.Models;
using edu.jhu.Cas.Util;

namespace RestApiTest
{
    [TestClass]
    public class JobTest
    {
        const string SIMPLE_JOB_REQUEST = "{\"Query\":\"SELECT 1 AS a\"}";
        const string JOBS_REQUEST_URI = "/contexts/mydb/jobs";
        const string JOBS_MANAGEMENT_URI = "/jobs";

        [TestMethod]
        public void JobLifeCycle()
        {
            RestApi.Models.JobInfo info;
            long jobid = CreateJob();
            info = GetJobInfo(jobid);
            CancelJob(jobid);
            System.Threading.Thread.Sleep(5000);
            info = GetJobInfo(jobid);
            Assert.IsTrue(QUERY_STATUS.CANCELED.Equals(info.Status) || QUERY_STATUS.CANCEL_PENDING.Equals(info.Status));
        }

        private long CreateJob()
        {
            string requestUri = ConfigurationManager.AppSettings["RestApiUri"] + JOBS_REQUEST_URI;
            var request = (HttpWebRequest)WebRequest.Create(requestUri);
            request.Method = "PUT";
            request.ContentType = "application/json";
            request.Headers.Add("X-Auth-Token", CredentialsManager.RegisteredUser.Token.Id);
            StreamWriter writer = new StreamWriter(request.GetRequestStream());
            writer.Write(SIMPLE_JOB_REQUEST);
            writer.Close();
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);


            StreamReader reader = new StreamReader(response.GetResponseStream());
            string s = reader.ReadToEnd();
            reader.Close();

            return long.Parse(s);
        }

        private void CancelJob(long jobid)
        {
            string requestUri = ConfigurationManager.AppSettings["RestApiUri"] + JOBS_MANAGEMENT_URI + "/" + jobid;
            var request = (HttpWebRequest)WebRequest.Create(requestUri);
            request.Method = "DELETE";
            request.ContentType = "application/json";
            request.Headers.Add("X-Auth-Token", CredentialsManager.RegisteredUser.Token.Id);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
        }

        private RestApi.Models.JobInfo GetJobInfo(long jobid)
        {
            string requestUri = ConfigurationManager.AppSettings["RestApiUri"] + JOBS_MANAGEMENT_URI+"/"+jobid;
            var request = (HttpWebRequest)WebRequest.Create(requestUri);
            request.Method = "GET";
            request.ContentType = "application/json";
            request.Headers.Add("X-Auth-Token", CredentialsManager.RegisteredUser.Token.Id);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);

            StreamReader reader = new StreamReader(response.GetResponseStream());
            string s = reader.ReadToEnd();
            reader.Close();

            RestApi.Models.JobInfo info = JsonConvert.DeserializeObject<RestApi.Models.JobInfo>(s);
            Assert.IsNotNull(info);
            Assert.AreEqual(jobid, info.JobID);
            
            return info;
        }

        [TestMethod]
        public void UnauthorizedCreateJob()
        {
            string requestUri = ConfigurationManager.AppSettings["RestApiUri"] + JOBS_REQUEST_URI;
            var request = (HttpWebRequest)WebRequest.Create(requestUri);
            request.Method = "PUT";
            request.ContentType = "application/json";
            request.Headers.Add("X-Auth-Token", "_invalid token_");
            StreamWriter writer = new StreamWriter(request.GetRequestStream());
            writer.Write("");
            writer.Close();
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Assert.Fail();
            }
            catch (WebException ex)
            {
                using (HttpWebResponse response = (HttpWebResponse)ex.Response)
                {
                    Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode);
                }
            }
        }
    }
}
