import com.liferay.counter.service.CounterLocalServiceUtil
import com.liferay.portal.kernel.executor.PortalExecutorManagerUtil
import com.liferay.portal.kernel.json.JSONArray
import com.liferay.portal.kernel.json.JSONFactoryUtil
import com.liferay.portal.kernel.json.JSONObject
import com.liferay.portal.kernel.log.Log
import com.liferay.portal.kernel.log.LogFactoryUtil
import com.liferay.portal.kernel.transaction.TransactionAttribute
import com.liferay.portal.kernel.transaction.TransactionInvokerUtil
import com.liferay.portal.kernel.util.StringPool
import com.liferay.portal.kernel.util.Validator
import com.liferay.portal.kernel.util.WebKeys
import com.liferay.portal.service.ServiceContextFactory
import com.liferay.portal.service.ServiceContextThreadLocal
import com.liferay.portal.theme.ThemeDisplay
import cz.vrk.pi.crm.custom.MemberSectionType
import cz.vrk.pi.crm.model.model.CategoryMembershipType
import cz.vrk.pi.crm.model.model.Member
import cz.vrk.pi.crm.model.model.MemberInfo
import cz.vrk.pi.crm.model.model.MemberPerson
import cz.vrk.pi.crm.model.service.CategoryMembershipTypeLocalServiceUtil
import cz.vrk.pi.crm.model.service.InfoTypeLocalServiceUtil
import cz.vrk.pi.crm.model.service.MemberInfoLocalServiceUtil
import cz.vrk.pi.crm.model.service.MemberInstitutionLocalServiceUtil
import cz.vrk.pi.crm.model.service.MemberLocalServiceUtil
import cz.vrk.pi.crm.model.service.MemberPersonLocalServiceUtil
import cz.vrk.pi.crm.model.service.MemberRelationLocalServiceUtil
import cz.vrk.pi.crm.model.service.RelationTypeLocalServiceUtil
import cz.vrk.pi.ou.model.model.Contact
import cz.vrk.pi.ou.model.model.ContactField
import cz.vrk.pi.ou.model.model.OrganizationExt
import cz.vrk.pi.ou.model.service.ContactFieldLocalServiceUtil
import cz.vrk.pi.ou.model.service.ContactLocalServiceUtil
import cz.vrk.pi.ou.model.service.OrganizationExtLocalServiceUtil
import vrk.pi.shared.PIModule
import vrk.pi.shared.ViewContext

import java.nio.file.Path
import java.nio.file.Paths
import java.text.SimpleDateFormat
import java.util.concurrent.Callable

static class Globals {

    //TEST
    static String identificationNumber = "69781621";
    //static String identificationNumber = "69781621";
}

try {
    out.println("Script Start");
    main();
    out.println("Script End");
} catch (Exception e) {
    out.println("""<div class="portlet-msg-error">${e}</div>""")
    e.printStackTrace(out)
}

def inTransaction(fun, log, ctx) {
    TransactionAttribute ta = new TransactionAttribute.Builder().setRollbackForClasses(Exception.class).build();
    TransactionInvokerUtil.invoke(ta, { fun(log, ctx); return null; } as java.util.concurrent.Callable);
}


def main() {
    def scriptThis = this;
    def log = LogFactoryUtil.getLog("cmku-importer")
    OrganizationExt organizationExt = OrganizationExtLocalServiceUtil.getOrganizationExt(Globals.identificationNumber)
    def viewContext = new ViewContext((ThemeDisplay) actionRequest.getAttribute(WebKeys.THEME_DISPLAY), PIModule.CRM, organizationExt.getOrganization())
    def serviceContext = ServiceContextFactory.getInstance(actionRequest)
    PortalExecutorManagerUtil.execute("cmku-importer", new Callable<Void>() {
        @Override
        Void call() throws Exception {
            ServiceContextThreadLocal.pushServiceContext(serviceContext)
            inTransaction(scriptThis.&importČMKU, log, viewContext)
            return null;
        }
    })

}

def importČMKU(Log log, ViewContext ctx) {
    log.info("Zacatek importu ČMKU")
    String where = "/opt/liferay-pi/imports/" + Globals.identificationNumber // Cesta k souboru
    String indexFile = "importCHKKontaktniOsoby.json"

    Path importDir = Paths.get(where)
    Path indexPath = importDir.resolve(indexFile)
    String json = indexPath.toFile().text
    JSONArray array = JSONFactoryUtil.createJSONArray(json)
    SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy")

    def categoryMembershipTypes = CategoryMembershipTypeLocalServiceUtil.getByOrganizationId(ctx.organizationId)
    Map<String, Long> categories = new HashMap<String, Long>()

    for (CategoryMembershipType cmt : categoryMembershipTypes) {
        categories.put(cmt.getMembershipTypeObj().getMembershipTypeType(), cmt.id)
    }

    for (i in 0..<array.length()) {
        JSONObject fileRow = array.getJSONObject(i)
        if (fileRow.has("CHKImportID") && Validator.isNotNull(fileRow.getString("CHKImportID"))) {
            //log.info(fileRow.getString("CHKImportID"))
            def chk = MemberLocalServiceUtil.getByOrganizationAndOldMemberIdAndOldSystem(ctx.organizationId, fileRow.getLong("CHKImportID"), "cmku");
            if (chk == null) {
                //log.info("CHK id: " + fileRow.getLong("CHKImportID"))
            } else {
                //log.info("CHK - nalezeno: " + chk.id)
                //log.info(fileRow)
                def member = MemberLocalServiceUtil.getByOrganizationAndOldMemberIdAndOldSystem(ctx.organizationId, fileRow.getLong("ImportID"), "cmku-osoby");
                if (member == null) {
                    // vytvoreni noveho
                    member = MemberLocalServiceUtil
                            .createMember(CounterLocalServiceUtil.increment(Member.class.getName()))
                    def person = MemberPersonLocalServiceUtil
                            .createMemberPerson(CounterLocalServiceUtil.increment(MemberPerson.class.getName()))

                    member.setNumber("")
                    member.setOrganizationId(ctx.organizationId);
                    member.setOldMemberId(fileRow.getLong("ImportID"))
                    member.setOldSystem("cmku-osoby")
                    member.setCountry("CZ")

                    person.setFirstName(fileRow.getString("Jméno"))
                    person.setLastName(fileRow.getString("Příjmení"))
                    person.setTitleBefore(fileRow.getString("Titul před"))
                    person.setTitleAfter(fileRow.getString("Titul za"))

                    member.setMemberPerson(person.getId());
                    member.setPerson(person);

                    MemberPersonLocalServiceUtil.updateMemberPerson(member.person);
                    member = MemberLocalServiceUtil.updateMember(member);

                    importKontakty(member, "CT_CONTACT_ADDRESS", null, fileRow.getString("Ulice"), fileRow.getString("Č.o."), fileRow.getString("Č. p ."), fileRow.getString("Obec") + " – " + fileRow.getString("Část obce"),
                            fileRow.getString("PSČ"), fileRow.getString("E-mail"), fileRow.getString("Telefon"), fileRow.getString("Mobil"), fileRow.getString("Fax"), fileRow.getString("Web"))

                    if (fileRow.has("ImportID")) {
                        def infoType = InfoTypeLocalServiceUtil.getByOrganizationAndMemberSectionAndName(ctx.organizationId, MemberSectionType.PERSON, "ImportID")
                        String value = fileRow.getString("ImportID");
                        if (Validator.isNotNull(value) && infoType != null) {
                            MemberInfo info = MemberInfoLocalServiceUtil
                                    .createMemberInfo(CounterLocalServiceUtil.increment(MemberInfo.class.getName()));
                            info.setMember(member.id);
                            info.setInfoType(infoType.id);
                            info.setValue(value)
                            info = MemberInfoLocalServiceUtil.updateMemberInfo(info);
                        }
                    }
                }

                //log.info("member nalezen " + member.id)

                def relationTypes = RelationTypeLocalServiceUtil.getByOrganizationIdAndName(ctx.organizationId, "Kontaktní osoba")
                if (!relationTypes.isEmpty()) {
                    def memberRelation = MemberRelationLocalServiceUtil.createMemberRelation(-1L);
                    memberRelation.setFromDate(new Date());
                    memberRelation.setMemberParent(chk.id)
                    memberRelation.setMemberChild(member.id)
                    memberRelation.setRelationType(relationTypes.get(0).id)
                    memberRelation = MemberRelationLocalServiceUtil.addMemberRelation(memberRelation);
                }


                if (fileRow.has("Plemeno")) {
                    def infoType = InfoTypeLocalServiceUtil.getByOrganizationAndMemberSectionAndName(ctx.organizationId, MemberSectionType.PERSON, "Plemeno")
                    String value = fileRow.getString("Plemeno");
                    if (Validator.isNotNull(value) && infoType != null) {
                        MemberInfo info = MemberInfoLocalServiceUtil
                                .createMemberInfo(CounterLocalServiceUtil.increment(MemberInfo.class.getName()));
                        info.setMember(member.id);
                        info.setInfoType(infoType.id);
                        info.setValue(value)
                        info = MemberInfoLocalServiceUtil.updateMemberInfo(info);
                    }
                }


            }
        }
    }

    log.info("Import ČMKU dokoncen")
}

def importKontakty(Member member, String contactType, String nazev, String ulice, String cisloPopisne, String cisloOrientacni, String mesto, String psc, String email, String telefon,
                   String mobil,
                   String fax, String www) {
    Contact contact = null;
    List<Contact> contactList = ContactLocalServiceUtil
            .getByClassPkAndNameAndContactType(member.getId(), Member.class.getName(), contactType);
    if (contactList.isEmpty()) {
        contact = ContactLocalServiceUtil.createContact();
        contact.setClassPK(member.getId());
        contact.setContactType(contactType);
        contact.setClassName(Member.class.getName());
        ContactLocalServiceUtil.updateContact(contact);
    } else {
        contact = contactList.get(0)
    }
    if (Validator.isNotNull(nazev)) {
        contact.setName(nazev)
    }
    if (Validator.isNotNull(ulice)) {
        contact.getContactAddress().setStreetText(ulice)
    }
    if (Validator.isNotNull(cisloPopisne)) {
        contact.getContactAddress().setDescriptiveNumber(cisloPopisne)
    }
    if (Validator.isNotNull(cisloOrientacni)) {
        contact.getContactAddress().setOrientationNumber(cisloOrientacni)
    }
    if (Validator.isNotNull(mesto)) {
        contact.getContactAddress().setMunicipalityText(mesto)
    }
    if (Validator.isNotNull(mesto)) {
        contact.getContactAddress().setZip(psc)
    }

    if (Validator.isNotNull(email)) {
        if (email.contains(StringPool.SEMICOLON)) {
            def splitEmails = email.split(StringPool.SEMICOLON)
            for (String singleEmail : splitEmails) {
                if (Validator.isNotNull(singleEmail.trim())) {
                    ContactField contactField = ContactFieldLocalServiceUtil.createContactField(
                            CounterLocalServiceUtil.increment(ContactField.class.getName()));
                    contactField.setContactFieldType("CFT_EMAIL");
                    contactField.setContactFieldValue(singleEmail);
                    contact.addContactField(contactField);
                }
            }
        } else {
            ContactField contactField = ContactFieldLocalServiceUtil.createContactField(
                    CounterLocalServiceUtil.increment(ContactField.class.getName()));
            contactField.setContactFieldType("CFT_EMAIL");
            contactField.setContactFieldValue(email);
            contact.addContactField(contactField);
        }
    }

    if (Validator.isNotNull(telefon)) {
        ContactField contactField = ContactFieldLocalServiceUtil.createContactField(
                CounterLocalServiceUtil.increment(ContactField.class.getName()));
        contactField.setContactFieldType("CFT_PHONE");
        contactField.setContactFieldValue(telefon);
        contact.addContactField(contactField);
    }

    if (Validator.isNotNull(mobil)) {
        ContactField contactField = ContactFieldLocalServiceUtil.createContactField(
                CounterLocalServiceUtil.increment(ContactField.class.getName()));
        contactField.setContactFieldType("CFT_MOBILE");
        contactField.setContactFieldValue(mobil);
        contact.addContactField(contactField);
    }

    if (Validator.isNotNull(fax)) {
        ContactField contactField = ContactFieldLocalServiceUtil.createContactField(
                CounterLocalServiceUtil.increment(ContactField.class.getName()));
        contactField.setContactFieldType("CFT_FAX");
        contactField.setContactFieldValue(fax);
        contact.addContactField(contactField);
    }

    if (Validator.isNotNull(www)) {
        ContactField contactField = ContactFieldLocalServiceUtil.createContactField(
                CounterLocalServiceUtil.increment(ContactField.class.getName()));
        contactField.setContactFieldType("CFT_WWW");
        contactField.setContactFieldValue(www);
        contact.addContactField(contactField);
    }

    ContactLocalServiceUtil.updateContact(contact);
}