package controllers;

import flexjson.JSONSerializer;
import models.*;
import models.contacts.Contact;
import models.contacts.Customer;
import models.contacts.FinancialInfo;
import models.contacts.Person;
import models.projects.Deliverable;
import models.projects.Project;
import org.joda.time.DateTime;
import play.Logger;
import play.data.validation.MaxSize;
import play.data.validation.Validation;
import play.db.jpa.JPA;
import play.mvc.Before;
import util.chat.ChatToken;

import javax.persistence.Query;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by dom on 13/12/2018.
 */
public class Contacts extends Application {

    @Before
    public static void getChatToken() {
        renderArgs.put("token", ChatToken.getToken());
    }

    public static void filterContacts(String ident) {
        AppUser user = AppUser.find("byUsername", Security.connected()).first();
        ChatToken.getToken();

        List<Contact> contacts = null;
        Logger.info("----------------------- " + ident);
        if (ident.equals("customers")) {
            renderArgs.put("active", "customers");
            renderArgs.put("pageHeader", "Πελάτες");
            renderArgs.put("pageHeaderDetail", "Λίστα καταγεγραμμένων πελατών ");
            contacts = Contact.find("select c from Contact c where dtype='Customer' and c.company =:comp ").setParameter("comp", user.company).fetch();

        } else if (ident.equals("associates")) {
            renderArgs.put("active", "associates");
            renderArgs.put("pageHeader", "Συνεργάτες");
            renderArgs.put("pageHeaderDetail", "Λίστα καταγεγραμμένων συνεργατών ");
            contacts = Contact.find("select c from Contact c where dtype='Person' and c.personType =:pertype and c.company =:comp ")
                    .setParameter("pertype", Person.PersonType.ASSOCIATE)
                    .setParameter("comp", user.company).fetch();
        }

        renderTemplate("app/views/contacts/filterContacts.html", ident);
    }

    public static void listContacts(String ident) {
        AppUser user = AppUser.find("byUsername", Security.connected()).first();
        String title = "";
        List<Contact> contacts = null;

        if (ident.equals("customers")) {
            title = "Customers ";
            contacts = Contact.find("select c from Contact c where dtype='Customer' and c.company =:comp ").setParameter("comp", user.company).fetch();
        } else if (ident.equals("associates")) {
            title = "associates ";
            contacts = Contact.find("select c from Contact c where c.company =:comp and ((dtype='Person' and c.personType =:pertype)  or dtype='AppUser') ")
                    .setParameter("pertype", Person.PersonType.ASSOCIATE)
                    .setParameter("comp", user.company).fetch();
        }
        Logger.info("----- " + ident);
        Logger.info("----- " + contacts.size());
        Logger.info("----- " + title);

        renderTemplate("app/views/contacts/listContacts.html", contacts, title, ident);
    }

    public static void addContact(Long id) {

        Contact con = null;
        renderArgs.put("active", "addContact");
        renderArgs.put("pageHeader", "Καρτέλα επαφής");
        renderArgs.put("pageHeaderDetail", "Φόρμα εισαγωγής νέας επαφής");

        if (id != null) {
            con = Contact.findById(id);
        }

        renderTemplate("app/views/contacts/addContact.html", con);
    }

    public static void addAssociate(Long id) {

        Person person = null;

        renderArgs.put("active", "associate");
        renderArgs.put("pageHeader", "Καρτέλα επαφής");
        renderArgs.put("pageHeaderDetail", "Φόρμα διαχείρισης συνεργατών");

        List<Project> projects = null;


        if (id != null) {
            person = Person.findById(id);
        }

        renderTemplate("app/views/contacts/addAssociate.html", person);

    }

    public static void doAddContact(Long id, @MaxSize(value = 50, message = "Όχι πάνω απο 50 χαρακτήρες") String name
            , @MaxSize(value = 150, message = "Όχι πάνω απο 150 χαρακτήρες") String fullName
            , @MaxSize(value = 25, message = "Όχι πάνω απο 25 χαρακτήρες") String doy
            , @MaxSize(value = 10, message = "Όχι πάνω απο 10 χαρακτήρες") String afm
            , @MaxSize(value = 25, message = "Όχι πάνω απο 25 χαρακτήρες") String address
            , @MaxSize(value = 25, message = "Όχι πάνω απο 25 χαρακτήρες") String district
            , @MaxSize(value = 10, message = "Όχι πάνω απο 10 χαρακτήρες") String number
            , @MaxSize(value = 10, message = "Όχι πάνω απο 10 χαρακτήρες") String zipcode
            , @MaxSize(value = 50, message = "Όχι πάνω απο 50 χαρακτήρες") String email
            , @MaxSize(value = 15, message = "Όχι πάνω απο 15 χαρακτήρες") String landline
            , @MaxSize(value = 15, message = "Όχι πάνω απο 15 χαρακτήρες") String fax
            , @MaxSize(value = 15, message = "Όχι πάνω απο 15 χαρακτήρες") String mobile) {
        validation.required(fullName);

        Logger.info("inside");
        if (Validation.hasErrors()) {
            Logger.info(validation.errorsMap().toString());
            params.flash();
            Validation.keep();
            addContact(id);
        }
        Customer customer = null;
        AppUser user = AppUser.find("byUsername", Security.connected()).first();
        if (id == null) {
            customer = new Customer();
            customer.name = name;
            customer.createDate = new DateTime();
            //customer.uploader = new AppUser();
            customer.company = user.company;
            customer.contactInfo = new ContactInfo(district, address, number, zipcode, email, landline, "", fax, mobile);
            customer.financialInfo = new FinancialInfo(afm, doy, fullName);
        } else {
            customer = Customer.findById(id);
            customer.name = name;
            customer.contactInfo = new ContactInfo(district, address, number, zipcode, email, landline, "", fax, mobile);
            customer.financialInfo = new FinancialInfo(afm, doy, fullName);
        }
        Logger.info("before save");
        customer.save();
        flash.put("success", "");
        addContact(customer.id);

    }

    public static void doaddPerson(Long personId, Long custId, String firstname, String lastname, Integer personType, String landline, String mobile, String email, String _AJAX) {
        Person person = null;
        Customer customer = null;
        AppUser user = AppUser.find("byUsername", Security.connected()).first();

        if (custId != null) {
            customer = Customer.findById(custId);
        }
        Logger.info("edv " + personId);

        if (personId == null) {
            person = new Person();
        } else {
            person = Person.findById(personId);
        }
        person.firstName = firstname;
        person.lastName = lastname;
        person.personType = Person.PersonType.values()[personType];
        person.contactInfo.landline = landline;
        person.contactInfo.mobile = mobile;
        person.contactInfo.email = email;
        person.customer = customer;
        person.company = user.company;
        person.save();
        if (_AJAX != null) {
            renderJSON(1);
        } else {
            renderTemplate("app/views/contacts/addAssociate.html", person);
        }

    }

    public static void listPersonsCard(Long customerId, Long projectId, Integer smallFlag) {
        Logger.info("++++++++++++++++++++++ " +projectId);
        Logger.info("+++++++++999999999999999+++++++++++++ " +smallFlag);
        Query query = null;
        AppUser user =  AppUser.find("byUsername", Security.connected()).first();
        String _PAGE = "";
        String title = "Persons ";
        List<Person> persons = null;
        Project project = null;
        Customer customer = null;
        if (customerId != null) {
            _PAGE = "customer";
            customer = Customer.findById(customerId);
            query = JPA.em().createQuery("select p from Person p where p.customer = :cust");
            query.setParameter("cust", customer);
            persons = query.getResultList();
        } else if (projectId != null && smallFlag == null) {
            _PAGE = "project";
            project = Project.findById(projectId);
            query = JPA.em().createQuery("select p from Contact p where p.company =:comp and (p.customer =:cust OR p.customer is null) and p.dtype='AppUser' ");
            query.setParameter("cust", project.customer);
            query.setParameter("comp", user.company);
            persons = query.getResultList();
        }
        else if (projectId != null && smallFlag == 1) {
            _PAGE = "project";
            project = Project.findById(projectId);
            query = JPA.em().createQuery("select u from AppUser u where u.id in (select s.user.id from Share s where s.project =:proj and s.user is not null ) ");
            query.setParameter("proj", project);

            persons = query.getResultList();
        }

        Logger.info("posoi " + persons.size());
        renderTemplate("app/views/contacts/listPersonsCard.html", persons, _PAGE, project, customer, project,smallFlag, user);

    }


    public static void getPersonDetails(Long personID) {

        try {
            Person person = Person.findById(personID);
            JSONSerializer serializer;
            serializer = new JSONSerializer()
                    .include("*.id.*")
                    .include("*.firstName.*")
                    .include("*.lastName.*")
                    .include("*.personType.*")
                    .include("*.contactInfo.landline.*")
                    .include("*.contactInfo.mobile.*")
                    .include("*.contactInfo.email.*")

                    .exclude("*");

            renderJSON(serializer.serialize(person));


        } catch (Exception ex) {
            Logger.info("ERROR getPersonDetails " + ex);
            renderJSON(0);
        }
    }

    public static void deletePerson(Long personID) {
        Person person = Person.findById(personID);
        if (person.hasTasks()) {
            renderJSON(-1);
        } else if (!person.isUser()) {
            renderJSON(-1);
        } else {
            person.delete();
            renderJSON(1);
        }

    }

    public static void listPersonDeliverables(Long personId) {
        AppUser person = Person.findById(personId);
        List<Deliverable> deliverables = null;
        List<Person> associates = null;
        Query query = null;
        query = JPA.em().createQuery("select p from Deliverable p where (p.id in (select s.deliverable.id from Share s where s.user =:usr and s.deliverable is not null)) OR p.uploader.id=:usr");
        query.setParameter("usr", person);

        deliverables = query.getResultList();

        renderTemplate("app/views/projects/listProjectDeliverables.html", deliverables);

    }



    public static void listPersonImages(Long userId) {
        AppUser user = AppUser.findById(userId);
        List<Document> documents = null;
        List<Person> associates = null;
        Query query = null;
        query = JPA.em().createQuery("select d from Document d where (d.id in (select s.document.id from Share s where s.user =:usr and s.document is not null ) OR d.uploader=:usr) and d.graphic = TRUE ");
        query.setParameter("usr", user);

        documents = query.getResultList();

        renderTemplate("app/views/contacts/listPersonImages.html", documents,associates);

    }



    public static void showCustomerTasks(Long customerId)
    {
        AppUser user = AppUser.find("byUsername", Security.connected()).first();
        Logger.info("************************");
        Customer cust = Customer.findById(customerId);
        boolean compactView = true;
        List<Task> tmp = null;
        List<Task> tasks = new ArrayList<>();
        Logger.info("_____________________________" +cust.employees);
        for (Person p : cust.employees) {
            if (p.taskSet.size() > 0) {
                Logger.info("to person " +p.getFullName());
                //first lets take the todos and not the deliverables
                tmp = p.taskSet.stream().filter(t -> t.getClass().getSimpleName().equals("Task")).collect(Collectors.toList());
                tasks.addAll(tmp);
            }
        }
        Logger.info("__________________77___________" +cust.projects);
        for (Project proj : cust.projects) {
            if (proj.tasks.size() > 0) {
                Logger.info("to project " +proj.name);
                tmp = proj.tasks.stream().filter(t -> t.getClass().getSimpleName().equals("Task")).collect(Collectors.toList());
                tasks.addAll(tmp);

            }
        }
        Logger.info("how many tasks of customer : "+tasks.size());
        renderTemplate("app/views/Application/showToDoList.html", tasks, user,compactView);
    }

    public static void updateUserRoles(Long appUserId, String role)
    {

        AppUser user = AppUser.findById(appUserId);

        if(user.roleInfo == null)
        {
            user.roleInfo = new RoleInfo();
            user.roleInfo.roleName = role;
            user.roleInfo.addToRoleDate = new DateTime();
            user.save();
        }
        else {
            user.roleInfo.roleName = role;
            user.roleInfo.addToRoleDate = new DateTime();
            user.save();
        }

        //TODO send an email to the user informing him for the role change
        renderJSON(1);
    }
}
