package eu.dnetlib.uoaadmintools.controllers;

import eu.dnetlib.uoaadmintools.dao.CommunityDAO;
import eu.dnetlib.uoaadmintools.dao.DivIdDAO;
import eu.dnetlib.uoaadmintools.dao.MongoDBCommunityDAO;
import eu.dnetlib.uoaadmintools.dao.PageDAO;
import eu.dnetlib.uoaadmintools.entities.*;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@CrossOrigin(origins = "*")
public class DivIdController {
    private final Logger log = Logger.getLogger(this.getClass());

    @Autowired
    private DivIdDAO divIdDAO;

    @Autowired
    private PageDAO pageDAO;

    @Autowired
    private CommunityController communityController;

    @Autowired
    private DivHelpContentController divHelpContentController;

    DivIdController() {}

    @RequestMapping(value = "/div", method = RequestMethod.GET)
    public List<DivId> getDivIds(@RequestParam(required = false) String page,
                                 @RequestParam(required = false) String name,
                                 @RequestParam(value = "communityId", required = false) String pid) {
        List<DivId> divIds = null;

        if(page != null && name != null) {
            DivId divId = divIdDAO.findByPagesContainingAndName(page, name);
            if(divId != null) {
                divIds = new ArrayList<>();
                divIds.add(divId);
            }
        } else if(page != null) {
            divIds = divIdDAO.findByPagesContaining(page);
        } else if(name != null) {
            DivId divId = divIdDAO.findByName(name);
            if(divId != null) {
                divIds = new ArrayList<>();
                divIds.add(divId);
            }
        } else {
            divIds = divIdDAO.findAll();
        }

        if(pid != null) {
            Iterator<DivId> iteratorDivIds = divIds.iterator();
            while(iteratorDivIds.hasNext()) {
                DivId divId = iteratorDivIds.next();
                if (pid.equals("openaire") && !divId.getOpenaire()) {
                    iteratorDivIds.remove();
                } else if (pid.equals("connect") && !divId.getConnect()) {
                    iteratorDivIds.remove();
                } else if(!pid.equals("openaire") && !pid.equals("connect") && !divId.getCommunities()){
                    iteratorDivIds.remove();
                }
            }
        }

        return divIds;
    }

    @RequestMapping(value = "/divFull", method = RequestMethod.GET)
    public List<DivIdResponse> getDivIdsFull(@RequestParam(required = false) String page,
                                             @RequestParam(required = false) String name,
                                             @RequestParam(value="communityId", required = false) String pid) {

        List<DivId> divIds = this.getDivIds(page, name, pid);

        List<DivIdResponse> divIdResponses = new ArrayList<>();
        for(DivId divId : divIds) {
            DivIdResponse divIdResponse = new DivIdResponse(divId);
            List<Page> pages = new ArrayList<>();
            for(String pageId : divId.getPages()) {
                pages.add(pageDAO.findById(pageId));
            }
            divIdResponse.setPages(pages);

            divIdResponses.add(divIdResponse);
        }

        return divIdResponses;
    }

    @RequestMapping(value = "/div/{id}", method = RequestMethod.GET)
    public DivId getDivId(@PathVariable(value = "id") String id) {
        return divIdDAO.findById(id);
    }

    @RequestMapping(value = "/divFull/{id}", method = RequestMethod.GET)
    public DivIdResponse getDivIdFull(@PathVariable(value = "id") String id) {
        DivId divId = divIdDAO.findById(id);
        return divIdResponseFromDivId(divId);
    }

    public DivIdResponse divIdResponseFromDivId(DivId divId) {
        DivIdResponse divIdResponse = new DivIdResponse(divId);
        List<Page> pages = new ArrayList<>();
        for(String pageId : divId.getPages()) {
            pages.add(pageDAO.findById(pageId));
        }
        divIdResponse.setPages(pages);
        return divIdResponse;
    }

    @RequestMapping(value = "/div", method = RequestMethod.DELETE)
    public void deleteAllDivIds() {
        divIdDAO.deleteAll();
    }

    @RequestMapping(value = "/div/save", method = RequestMethod.POST)
    public DivIdResponse insertDivId(@RequestBody DivIdResponse divIdResponse) {
        DivId divId = this.getDivIdByDivIdResponse(divIdResponse);

        DivId savedDivId = divIdDAO.save(divId);
        divIdResponse.setId(savedDivId.getId());

        return this.getDivIdFull(divId.getId());
    }

    private DivId getDivIdByDivIdResponse(DivIdResponse divIdResponse) {
        DivId divId = new DivId();
        divId.setId(divIdResponse.getId());
        divId.setName(divIdResponse.getName());
        divId.setOpenaire(divIdResponse.getOpenaire());
        divId.setConnect(divIdResponse.getConnect());
        divId.setCommunities(divIdResponse.getCommunities());

        List<Page> fullPages = divIdResponse.getPages();
        List<String> pages = new ArrayList<String>();
        for(Page page : fullPages) {
            pages.add(page.getId());
        }
        divId.setPages(pages);

        return divId;
    }

    @RequestMapping(value = "/div/update", method = RequestMethod.POST)
    public DivIdResponse updateDivId(@RequestBody DivIdResponse divIdResponse) {
        /*
        DivId divId = divIdDAO.findById(_divId.getId());
        divId.setName(_divId.getName());
        divId.setPages(_divId.getPages());
        divIdDAO.save(divId);
        return this.getDivIdFull(divId.getId());
        */
        DivId divIdOld = divIdDAO.findById(divIdResponse.getId());
        DivId divId = this.getDivIdByDivIdResponse(divIdResponse);
        divIdDAO.save(divId);

        boolean openaireEnabled = divId.getOpenaire();
        boolean connectEnabled = divId.getConnect();

        if(divId.getCommunities() && !divIdOld.getCommunities()) {
            List<Community> communities = communityController.getAllCommunities();
            for( Community community : communities ) {
                if(!community.getPid().equals("openaire") && !community.getPid().equals("connect")) {
                    divHelpContentController.addDivHelpContentsInCommunity(community.getPid(), community.getId(), divId.getName());
                }
            }
        }
        if(openaireEnabled && !divIdOld.getOpenaire()) {
            Community community = communityController.getCommunity("openaire");
            divHelpContentController.addDivHelpContentsInCommunity(community.getPid(), community.getId(), divId.getName());
        }

        if(connectEnabled && !divIdOld.getConnect()) {
            Community community = communityController.getCommunity("connect");
            divHelpContentController.addDivHelpContentsInCommunity(community.getPid(), community.getId(), divId.getName());
        }

        if(!divId.getCommunities()) {
            List<Community> communities = communityController.getAllCommunities();
            for( Community community : communities ) {
                if(!community.getPid().equals("openaire") && !community.getPid().equals("connect")) {
                    // delete div contents related to this divId
                    List<DivHelpContentResponse> divHelpContentResponses = divHelpContentController.getDivHelpContents(community.getPid(), null, divId.getName(), null);
                    for(DivHelpContentResponse divHelpContentResponse : divHelpContentResponses) {
                        divHelpContentController.deleteDivHelpContent(divHelpContentResponse.getId());
                    }
                }
            }
        }

        if(!openaireEnabled) {
            Community community = communityController.getCommunity("openaire");

            // delete div contents related to this divId
            List<DivHelpContentResponse> divHelpContentResponses = divHelpContentController.getDivHelpContents("openaire", null, divId.getName(), null);
            for(DivHelpContentResponse divHelpContentResponse : divHelpContentResponses) {
                divHelpContentController.deleteDivHelpContent(divHelpContentResponse.getId());
            }
        }

        if(!connectEnabled) {
            Community community = communityController.getCommunity("connect");

            // delete div contents related to this divId
            List<DivHelpContentResponse> divHelpContentResponses = divHelpContentController.getDivHelpContents("connect", null, divId.getName(), null);
            for(DivHelpContentResponse divHelpContentResponse : divHelpContentResponses) {
                divHelpContentController.deleteDivHelpContent(divHelpContentResponse.getId());
            }
        }

        return divIdResponse;
    }

    @RequestMapping(value = "/div/delete", method = RequestMethod.POST)
    public Boolean deleteDivIds(@RequestBody List<String> divIds) throws Exception {
        for (String id: divIds) {
            DivId divId = divIdDAO.findById(id);

            // delete div contents related to this divId
            List<DivHelpContentResponse> divHelpContentResponses = divHelpContentController.getDivHelpContents(null, null, divId.getName(), null);
            for(DivHelpContentResponse divHelpContentResponse : divHelpContentResponses) {
                divHelpContentController.deleteDivHelpContent(divHelpContentResponse.getId());
            }

            divIdDAO.delete(id);
        }
        return true;
    }

    @RequestMapping(value = "/div/{id}", method = RequestMethod.DELETE)
    public void deleteDivId(@PathVariable(value = "id") String id) {
        divIdDAO.delete(id);
    }

    @RequestMapping(value = "/div/pages", method = RequestMethod.GET)
    public Set<String> getDivIdsPages(@RequestParam(value="communityId", required = false) String pid) {
        List<DivId> divIds = null;
        Set<String> hasCommunityPageDivIds = new HashSet<>();

        if(pid != null) {
            if(pid.equals("openaire")) {
                divIds = divIdDAO.findByOpenaire(true);
            } else if(pid.equals("connect")) {
                divIds = divIdDAO.findByConnect(true);
            } else {
                divIds = divIdDAO.findByCommunities(true);
            }
        } else {
            divIds = divIdDAO.findAll();
        }

        for(DivId divId : divIds) {
            for(String pageId : divId.getPages()) {
                hasCommunityPageDivIds.add(pageId);
            }
        }
        return hasCommunityPageDivIds;
    }

}
