using System;
using System.Data.Linq;
using System.Linq;
using System.Net;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using System.Text;
using System.Web;
using Microsoft.ServiceModel.DomainServices.LinqToSql;
using TaskIt.Web.Models;

namespace TaskIt.Web.Services
{
    // TODO: Wire up authentication (Windows/ASP.NET Forms) and uncomment the following to disable anonymous access
    // Also consider adding roles to restrict access as appropriate.
    // [RequiresAuthentication]
    [EnableClientAccess]
    public class DataService2 : LinqToSqlDomainService<DataModelDataContext>
    {
        public IQueryable<Contact> GetContacts(long userID)
        {
            return DataContext.Contacts.Where(c => c.UserID == userID || c.UserID == 2).OrderBy(c => c.Name);
        }

        public void InsertContact(Contact contact)
        {
            contact.CreatedDate = DateTime.Now;
            contact.ModifiedDate = DateTime.Now;
            DataContext.Contacts.InsertOnSubmit(contact);
        }

        public void UpdateContact(Contact contact)
        {
            contact.ModifiedDate = DateTime.Now;
            DataContext.Contacts.Attach(contact, ChangeSet.GetOriginal(contact));
        }

        public void DeleteContact(Contact contact)
        {
            DataContext.Contacts.Attach(contact);
            DataContext.Contacts.DeleteOnSubmit(contact);
        }

        public IQueryable<ContactNote> GetContactNotes(long contactID)
        {
            return DataContext.ContactNotes.Where(n => n.ContactID == contactID);
        }

        public void InsertContactNote(ContactNote contactNote)
        {
            contactNote.CreatedDate = DateTime.Now;
            DataContext.ContactNotes.InsertOnSubmit(contactNote);
        }

        public IQueryable<Context> GetContexts(long userID)
        {
            return DataContext.Contexts.Where(c => c.UserID == userID || c.UserID == 2).OrderBy(c => c.Name);
        }

        public void InsertContext(Context context)
        {
            context.CreatedDate = DateTime.Now;
            context.ModifiedDate = DateTime.Now;
            DataContext.Contexts.InsertOnSubmit(context);
        }

        public void UpdateContext(Context context)
        {
            context.ModifiedDate = DateTime.Now;
            DataContext.Contexts.Attach(context, ChangeSet.GetOriginal(context));
        }

        public void DeleteContext(Context context)
        {
            DataContext.Contexts.Attach(context);
            DataContext.Contexts.DeleteOnSubmit(context);
        }

        public IQueryable<ContextNote> GetContextNotes(long contextID)
        {
            return DataContext.ContextNotes.Where(n => n.ContextID == contextID);
        }

        public void InsertContextNote(ContextNote contextNote)
        {
            contextNote.CreatedDate = DateTime.Now;
            DataContext.ContextNotes.InsertOnSubmit(contextNote);
        }

        public IQueryable<Priority> GetPriorities()
        {
            return DataContext.Priorities;
        }

        public IQueryable<Project> GetProjects(long userID)
        {
            return DataContext.Projects.Where(p => p.UserID == userID || p.UserID == 2).OrderBy(p => p.Name);
        }

        public IOrderedEnumerable<Project> GetProjectsDueThisWeek(long userID)
        {
            return DataContext.GetProjectsDueThisWeek(userID).OrderBy(p => p.DueDate);
        }

        public void InsertProject(Project project)
        {
            project.CreatedDate = DateTime.Now;
            project.ModifiedDate = DateTime.Now;
            DataContext.Projects.InsertOnSubmit(project);
        }

        public void UpdateProject(Project project)
        {
            project.ModifiedDate = DateTime.Now;
            DataContext.Projects.Attach(project, ChangeSet.GetOriginal(project));
        }

        public void DeleteProject(Project project)
        {
            DataContext.Projects.Attach(project);
            DataContext.Projects.DeleteOnSubmit(project);
        }

        public IQueryable<ProjectNote> GetProjectNotes(long projectID)
        {
            return DataContext.ProjectNotes.Where(n => n.ProjectID == projectID);
        }

        public void InsertProjectNote(ProjectNote projectNote)
        {
            projectNote.CreatedDate = DateTime.Now;
            DataContext.ProjectNotes.InsertOnSubmit(projectNote);
        }

        public IQueryable<Task> GetTasksByTaskCategory(long userID, long taskCategoryID, bool showCompleted, bool showDue)
        {
            if (showCompleted)
            {
                return showDue ?
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.TaskCategoryID == taskCategoryID).Where(t => t.CompletionDate != null).Where(t => t.DueDate != null).OrderBy(t =>  t.CompletionDate) :
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.TaskCategoryID == taskCategoryID).Where(t => t.CompletionDate != null).OrderBy(t => t.CompletionDate);
            }            
            return showDue ?
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.TaskCategoryID == taskCategoryID).Where(t => t.CompletionDate == null).Where(t => t.DueDate != null).OrderBy(t => t.DueDate) :
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.TaskCategoryID == taskCategoryID).Where(t => t.CompletionDate == null).OrderBy(t => t.DueDate);           
        }

        public IQueryable<Task> GetAllTasks(long userID, bool showCompleted, bool showDue)
        {
            if (showCompleted)
            {
                return showDue ?
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.CompletionDate != null).Where(t => t.DueDate != null).OrderBy(t => t.CompletionDate) :
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.CompletionDate != null).OrderBy(t => t.CompletionDate);
            }
            return showDue ?
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.CompletionDate == null).Where(t => t.DueDate != null).OrderBy(t => t.DueDate) :
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.CompletionDate == null).OrderBy(t => t.DueDate);
        }

        public IQueryable<Task> GetTasksByProject(long userID, long projectID, bool showCompleted, bool showDue)
        {
            if (showCompleted)
            {
                return showDue ?
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ProjectID == projectID).Where(t => t.CompletionDate != null).Where(t => t.DueDate != null).OrderBy(t => t.CompletionDate) :
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ProjectID == projectID).Where(t => t.CompletionDate != null).OrderBy(t => t.CompletionDate);
            }
            return showDue ?
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ProjectID == projectID).Where(t => t.CompletionDate == null).Where(t => t.DueDate != null).OrderBy(t => t.DueDate) :
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ProjectID == projectID).Where(t => t.CompletionDate == null).OrderBy(t => t.DueDate);
        }

        public ISingleResult<Task> GetBlogPosts()
        {
            return DataContext.GetBlogPosts();
        }

        public ISingleResult<Task> GetVideos()
        {
            return DataContext.GetVideos();
        }

        public ISingleResult<Task> GetWebinars()
        {
            return DataContext.GetWebinars();
        }

        public IQueryable<Task> GetTasksByContext(long userID, long contextID, bool showCompleted, bool showDue)
        {
            if (showCompleted)
            {
                return showDue ?
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ContextID == contextID).Where(t => t.CompletionDate != null).Where(t => t.DueDate != null).OrderBy(t => t.CompletionDate) :
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ContextID == contextID).Where(t => t.CompletionDate != null).OrderBy(t => t.CompletionDate);
            }
            return showDue ?
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ContextID == contextID).Where(t => t.CompletionDate == null).Where(t => t.DueDate != null).OrderBy(t => t.DueDate) :
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ContextID == contextID).Where(t => t.CompletionDate == null).OrderBy(t => t.DueDate);
        }

        public IQueryable<Task> GetTasksByContact(long userID, long contactID, bool showCompleted, bool showDue)
        {
            if (showCompleted)
            {
                return showDue ?
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ContactID == contactID).Where(t => t.CompletionDate != null).Where(t => t.DueDate != null).OrderBy(t => t.CompletionDate) :
                    DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ContactID == contactID).Where(t => t.CompletionDate != null).OrderBy(t => t.CompletionDate);
            }
            return showDue ?
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ContactID == contactID).Where(t => t.CompletionDate == null).Where(t => t.DueDate != null).OrderBy(t => t.DueDate) :
                DataContext.Tasks.Where(t => t.UserID == userID).Where(t => t.ContactID == contactID).Where(t => t.CompletionDate == null).OrderBy(t => t.DueDate);
        }

        public IOrderedEnumerable<Task> GetTasksDueThisWeek(long userID)
        {
            return DataContext.GetTasksDueThisWeek(userID).OrderBy(t => t.DueDate);
        }

        //public void UpdateTasksDueThisWeek(TasksDueThisWeek taskDueThisWeek)
        //{
        //    var task = DataContext.Tasks.Where(t => t.ID == taskDueThisWeek.ID).First();
        //    UpdateTask(task);
        //}

        //public void DeleteTaskDueThisWeek(TasksDueThisWeek taskDueThisWeek)
        //{
        //    var task = DataContext.Tasks.Where(t => t.ID == taskDueThisWeek.ID).First();
        //    DataContext.Tasks.DeleteOnSubmit(task);
        //}

        //public IOrderedEnumerable<OverdueTasks> GetOverdueTasks(long userID)
        //{
        //    return DataContext.GetOverdueTasks(userID).OrderBy(t => t.DueDate);
        //}

        public IOrderedEnumerable<Task> GetOverdueTasks(long userID)
        {
            return DataContext.GetOverdueTasks(userID).OrderBy(t => t.DueDate);
        }

        public void InsertTask(Task task)
        {
            task.CreatedDate = DateTime.Now;
            task.ModifiedDate = DateTime.Now;
            DataContext.Tasks.InsertOnSubmit(task);
        }

        public void UpdateTask(Task task)
        {
            task.ModifiedDate = DateTime.Now;
            DataContext.Tasks.Attach(task, ChangeSet.GetOriginal(task));
        }

        public void DeleteTask(Task task)
        {
            DataContext.Tasks.Attach(task);
            DataContext.Tasks.DeleteOnSubmit(task);
        }

        public IQueryable<TaskNote> GetTaskNotes(long taskID)
        {
            return DataContext.TaskNotes.Where(n => n.TaskID == taskID);
        }

        public void InsertTaskNote(TaskNote taskNote)
        {
            taskNote.CreatedDate = DateTime.Now;
            DataContext.TaskNotes.InsertOnSubmit(taskNote);
        }

        public IQueryable<TaskCategory> GetTaskCategories()
        {
            return DataContext.TaskCategories;
        }

        public IQueryable<TaskItUser> GetUsers()
        {
            return DataContext.TaskItUsers;
        }

        public void InsertUser(TaskItUser user)
        {
            user.CreatedDate = DateTime.Now;
            user.ModifiedDate = DateTime.Now;
            DataContext.TaskItUsers.InsertOnSubmit(user);
        }

        public void UpdateUser(TaskItUser user)
        {
            user.ModifiedDate = DateTime.Now;
            DataContext.TaskItUsers.Attach(user, ChangeSet.GetOriginal(user));
        }

        public void DeleteUser(TaskItUser user)
        {
            DataContext.TaskItUsers.Attach(user);
            DataContext.TaskItUsers.DeleteOnSubmit(user);
        }

        public ISingleResult<TasksOverview> GetTasksOverview(long userID)
        {
            return DataContext.GetTasksOverview(userID);
        }

        public void Tweet(string username, string password, string message)
        {
            // encode the username/password
            var user = Convert.ToBase64String(Encoding.UTF8.GetBytes(username + ":" + password));
            // determine what we want to upload as a status
            var parameters = string.Format("status={0}&source={1}", HttpUtility.HtmlEncode(message), "TaskIt");
            var bytes = Encoding.ASCII.GetBytes(parameters);
            // connect with the update page
            var request = (HttpWebRequest)WebRequest.Create("http://twitter.com/statuses/update.xml");
            // set the method to POST
            request.Method = "POST";
            // thanks to argodev for this recent change!
            request.ServicePoint.Expect100Continue = false;
            // set the authorisation levels
            request.Headers.Add("Authorization", "Basic " + user);
            request.ContentType = "application/x-www-form-urlencoded";
            // set the length of the content
            request.ContentLength = bytes.Length;
            // set up the stream
            var reqStream = request.GetRequestStream();
            // write to the stream
            reqStream.Write(bytes, 0, bytes.Length);
            // close the stream
            reqStream.Close();
        }
    }
}