/*
 *******************************************************************************
 * Copyright (c) 2018 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************
*/

package org.eclipse.openk.core.controller;

import org.apache.log4j.Logger;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.openk.api.*;
import org.eclipse.openk.api.mail.EmailTemplatePaths;
import org.eclipse.openk.common.mapper.generic.GenericApiToDbMapper;
import org.eclipse.openk.common.util.ResourceLoaderBase;
import org.eclipse.openk.core.exceptions.HttpStatusException;
import org.eclipse.openk.db.dao.*;
import org.eclipse.openk.db.model.*;

import javax.persistence.EntityManager;
import java.time.Instant;
import java.util.*;

import static org.eclipse.openk.common.JsonGeneratorBase.getGson;

public class MasterDataBackendController {
    protected static final Logger logger = Logger.getLogger(MasterDataBackendController.class);

    public List<String> getEmailAddressesFromTemplates()  {
        List<String> recipientAddressesAllList = new ArrayList<>();
        Set<String> recipientAddressesUniqueList = new HashSet<>();

        //fetch names of relevant emailTemplates
        BackendSettings bSettings = BackendConfig.getInstance().getBackendSettings();
        String emailTemplateAddressesForNotification = bSettings.getEmailTemplateAddressesForNotification();
        String[] templateNameList = emailTemplateAddressesForNotification.split(",");

        EmailTemplatePaths paths = BackendConfig.getInstance().getEmailTemplatePaths();

        //TODO: refactoren, z.B. Möglichkeit schaffen, einen Template-Path direkt mit Hilfe des Template-Namens zu holen
        //fetch emailTemplates by the aid of their names
        List<String> relevantEmailTemplates = new ArrayList<>();
        for(String templateName: templateNameList) {
            if (templateName.contains("active"))
                relevantEmailTemplates.add(paths.getActiveEmailTemplate());
            if (templateName.contains("applied"))
                relevantEmailTemplates.add(paths.getAppliedEmailTemplate());
            if (templateName.contains("approved"))
                relevantEmailTemplates.add(paths.getApprovedEmailTemplate());
            if (templateName.contains("cancelled"))
                relevantEmailTemplates.add(paths.getCancelledEmailTemplate());
            if (templateName.contains("closed"))
                relevantEmailTemplates.add(paths.getClosedEmailTemplate());
            if (templateName.contains("finished"))
                relevantEmailTemplates.add(paths.getFinishedEmailTemplate());
            if (templateName.contains("forapproval"))
                relevantEmailTemplates.add(paths.getForapprovalEmailTemplate());
            if (templateName.contains("inwork"))
                relevantEmailTemplates.add(paths.getInworkEmailTemplate());
            if (templateName.contains("rejected"))
                relevantEmailTemplates.add(paths.getRejectedEmailTemplate());
            if (templateName.contains("released"))
                relevantEmailTemplates.add(paths.getReleasedEmailTemplate());
            if (templateName.contains("requested"))
                relevantEmailTemplates.add(paths.getRequestedEmailTemplate());
            if (templateName.contains("workfinished"))
                relevantEmailTemplates.add(paths.getWorkfinishedEmailTemplate());
        }

        //fetch emailAddresses from relevant emailTemplates
        String[] recipientsSplit;
        String recipientsTo;
        String[] recipientAddresses;

        for(String templatePath: relevantEmailTemplates) {

            ResourceLoaderBase loaderBase = new ResourceLoaderBase();
            String templateString = loaderBase.loadFromPath(templatePath);

            recipientsSplit = templateString.split("CC");
            recipientsTo = recipientsSplit[0].trim().replace("To:", "");
            if(!recipientsTo.isEmpty()) {
                recipientAddresses = recipientsTo.split(",");
                recipientAddressesAllList.addAll(Arrays.asList(recipientAddresses));
            }
        }

        recipientAddressesAllList.replaceAll(String::trim);
        recipientAddressesUniqueList.addAll(recipientAddressesAllList);
        List<String> retList= new ArrayList<>(recipientAddressesUniqueList);

        Collections.sort(retList);
        return retList;
    }

    public List<Branch> getBranches()  {
        List<Branch> vmList = new java.util.ArrayList<>();

        try (AutoCloseEntityManager em = createEm()) {
            RefBranchDao bDao = createRefBranchDao(em);

            List<RefBranch>mList = bDao.getBranchesInTx();
            GenericApiToDbMapper mapper = new GenericApiToDbMapper();
            mList.forEach(m -> vmList.add(mapper.mapToViewModel(Branch.class, m) ) );
        }
        return vmList;
    }


    public List<BranchLevel> getBranchLevelsByBranch(int id)  {
        List<BranchLevel> vmList = new java.util.ArrayList<>();

        try (AutoCloseEntityManager em = createEm()) {
            RefBranchLevelDao blDao = createRefBranchLevelDao(em);

            List<RefBranchLevel>mList = blDao.getBranchLevelsByBranchId(id);
            GenericApiToDbMapper mapper = new GenericApiToDbMapper();
            mList.forEach(m -> vmList.add(mapper.mapToViewModel(BranchLevel.class, m) ) );
        }

        return vmList;
    }

    public List<GmStatus> getGmStatus()  {
        List<GmStatus> vmList = new java.util.ArrayList<>();

        try (AutoCloseEntityManager em = createEm()) {
            RefGmStatusDao sDao = createRefGmStatusDao(em);

            List<RefGmStatus>mList = sDao.getGmStatusInTx();
            GenericApiToDbMapper mapper = new GenericApiToDbMapper();
            mList.forEach(m -> vmList.add(mapper.mapToViewModel(GmStatus.class, m)));
        }
        return vmList;
    }

    public List<CostCenter> getCostCenters()  {
        List<CostCenter> vmList = new java.util.ArrayList<>();

        try (AutoCloseEntityManager em = createEm()) {
            RefCostCenterDao costCenterDao = createRefCostCenterDao(em);

            List<RefCostCenter>mList = costCenterDao.getCostCentersInTx();
            GenericApiToDbMapper mapper = new GenericApiToDbMapper();
            mList.forEach(m -> vmList.add(mapper.mapToViewModel(CostCenter.class, m)));
        }
        return vmList;
    }



    public List<Territory> getTerritories()  {
        List<Territory> vmList = new java.util.ArrayList<>();

        try (AutoCloseEntityManager em = createEm()){
            RefTerritoryDao territoryDao = createRefTerritoryDao(em);

            List<RefTerritory>mList = territoryDao.getTerritoriesInTx();
            GenericApiToDbMapper mapper = new GenericApiToDbMapper();
            mList.forEach(m -> vmList.add(mapper.mapToViewModel(Territory.class, m)));
        }
        return vmList;
    }

    public UserSettings getUserSettings(String username, String settingType)  throws HttpStatusException{
        UserSettings userSettings = new UserSettings();

        try (AutoCloseEntityManager em = createEm()) {
            TblUserSettingsDao userSettingsDao = createRefUserSettingsDao(em);

            TblUserSettings tblUserSettings = userSettingsDao.getUserSettingsBySettingType(username, settingType);
            GenericApiToDbMapper mapper = new GenericApiToDbMapper();
            userSettings = mapper.mapToViewModel(UserSettings.class,tblUserSettings);

        }
        catch(HttpStatusException e) {
            logger.error("getUserSettings", e);
            throw new HttpStatusException(org.apache.http.HttpStatus.SC_NOT_FOUND, e.getMessage());
        }
        return userSettings;
    }

    public UserSettings storeUserSettings(String changeUser, UserSettings userSettings)  throws HttpStatusException{

        TblUserSettings tblUsDb = new TblUserSettings();
        GenericApiToDbMapper mapper = new GenericApiToDbMapper();
        TblUserSettings tblUserSettings = mapper.mapFromViewModel(TblUserSettings.class, userSettings);
        tblUserSettings.setModUser(changeUser);
        tblUserSettings.setModDate(Date.from(Instant.now()));

        try (AutoCloseEntityManager em = createEm()) {
            TblUserSettingsDao userSettingsDao = createRefUserSettingsDao(em);

            TblUserSettings tblDb = userSettingsDao.getUserSettingsBySettingType(changeUser, userSettings.getSettingType());

            if(tblDb.getId() != null){
                // entity should exist before it is updated
                userSettingsDao.getEM().getTransaction().begin();
                tblUsDb =  userSettingsDao.updateUserSettingsInDB(tblUserSettings, tblDb);
                userSettingsDao.getEM().getTransaction().commit();
            }
            else{
                userSettingsDao.getEM().getTransaction().begin();
                tblUsDb =  userSettingsDao.createUserSettingsInDb(changeUser, tblUserSettings);
                userSettingsDao.getEM().getTransaction().commit();
            }
        }
        catch (HttpStatusException e) {
            logger.error("Error in storeUserSettings", e);
            throw new HttpStatusException(HttpStatus.INTERNAL_SERVER_ERROR_500);
        }
        return mapper.mapToViewModel(UserSettings.class, tblUsDb);
    }


    public BackendSettings getBackendSettings() {
        ResourceLoaderBase loaderBase = new ResourceLoaderBase();
        String backendSettingsString = loaderBase.loadFromPath("./backendSettings.json");
        return getGson().fromJson(backendSettingsString, BackendSettings.class);
    }

    protected RefBranchDao createRefBranchDao(EntityManager em) {
        return new RefBranchDao(em);
    }

    protected RefBranchLevelDao createRefBranchLevelDao(EntityManager em) { return new RefBranchLevelDao(em); }

    protected RefGmStatusDao createRefGmStatusDao(EntityManager em) {
        return new RefGmStatusDao(em);
    }

    protected RefCostCenterDao createRefCostCenterDao(EntityManager em) {
        return new RefCostCenterDao(em);
    }

    protected RefTerritoryDao createRefTerritoryDao(EntityManager em) { return new RefTerritoryDao(em); }

    protected TblUserSettingsDao createRefUserSettingsDao(EntityManager em) { return new TblUserSettingsDao(em); }

    protected AutoCloseEntityManager createEm() {
        return new AutoCloseEntityManager(EntityHelper.getEMF().createEntityManager());
    }

}

