package eu.dnetlib.server;

import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.Form;
import com.github.gwtbootstrap.client.ui.Modal;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.gwt.user.server.rpc.SerializationPolicy;
import eu.dnetlib.client.DataService;
import eu.dnetlib.goldoa.domain.*;
import eu.dnetlib.goldoa.domain.Currency;
import eu.dnetlib.goldoa.domain.stats.*;
import eu.dnetlib.goldoa.service.*;
import eu.dnetlib.goldoa.service.CurrencyConverter;
import eu.dnetlib.goldoa.service.stats.StatsManager;
import eu.dnetlib.shared.*;
import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.mail.MessagingException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Created by stefania on 3/4/15.
 */
public class DataServiceImpl extends RemoteServiceServlet implements DataService {

    private OrganizationManager organizationManager = null;
    private UserManager userManager = null;
    private ProjectManager projectManager = null;
    private PublisherManager publisherManager = null;
    private JournalManager journalManager = null;
    private PublicationManager publicationManager = null;
    private RequestManager requestManager = null;
    private EligibilityManager eligibilityManager = null;
    private BudgetManager budgetManager = null;
    private ContactManager contactManager = null;
    private HelpManager helpManager = null;
    private CurrencyConverter currencyConverter = null;
    private StatsManager statsManager = null;
    private AlternativeFundingBidManager alternativeFundingBidManager = null;

    private String hostName;
    private String publicCaptchaKey = null;
    private String privateCaptchaKey = null;
    private boolean firstRound = false;
    private Log log = LogFactory.getLog(DataServiceImpl.class);
    private boolean sendPendingMails = false;

    public void init(ServletConfig config) throws ServletException {

        super.init(config);

        ApplicationContext context = WebApplicationContextUtils
                .getWebApplicationContext(getServletContext());

        this.organizationManager = (OrganizationManager) context.getBean("organizationManager");
        this.userManager = (UserManager) context.getBean("userManager");
        this.projectManager = (ProjectManager) context.getBean("projectManager");
        this.publisherManager = (PublisherManager) context.getBean("publisherManager");
        this.journalManager = (JournalManager) context.getBean("journalManager");
        this.publicationManager = (PublicationManager) context.getBean("publicationManager");
        this.requestManager = (RequestManager) context.getBean("requestManager");
        this.eligibilityManager = (EligibilityManager) context.getBean("eligibilityManager");
        this.budgetManager = (BudgetManager) context.getBean("budgetManager");
        this.contactManager = (ContactManager) context.getBean("contactManager");
        this.helpManager = (HelpManager) context.getBean("helpManager");
        this.currencyConverter = (CurrencyConverter) context.getBean("currencyConverter");
        this.statsManager = (StatsManager) context.getBean("statsManager");
        this.alternativeFundingBidManager = (AlternativeFundingBidManager) context.getBean("alternativeFundingBidManager");

        this.publicCaptchaKey = (String) context.getBean("goldoa.recaptcha.key.public");
        this.privateCaptchaKey = (String) context.getBean("goldoa.recaptcha.key.private");
        this.hostName = (String) context.getBean("goldoa.hostname");

       /* if(!sendPendingMails){
            sendPendingMails = true;
            requestManager.sendEmailForPendingIncompleteRequests();
            requestManager.sendEmailForPendingConditionallyApprovedRequests();
        }*/

    }

    @Override
    public InitLoad load(String hash, String email, String token, String cookie) {

        InitLoad initLoad = new InitLoad();
        String message = null;
        String goTo = "home";
        User user = null;

        String hashValue = "home";
        if(hash!=null && !hash.equals(""))
                hashValue = hash.substring(1);

        if(hashValue.equals("activate")) {

            if (email != null && token != null) {

                try {
                    user = userManager.activate(email, token);
                    goTo = "myAccount";

                } catch (PersonManagerException pme) {
                    if(pme.getErrorCause().equals(PersonManagerException.ErrorCause.NOT_EXISTS))
                        message = "Invalid email or activation token";
                    else
                        message = "Activation token has expired";
                }

            } else {
                message = "Invalid activation URL";
            }

        } else {

            if(cookie!=null) {

                try {
                    user = userManager.getByEmail(cookie);
                } catch (PersonManagerException pme) {
                    //TODO do we want to display a message like that or not?
                    if(pme.getErrorCause().equals(PersonManagerException.ErrorCause.NOT_EXISTS))
                        message = "User does not exist";
                }
                goTo = hashValue;

            } else {

                goTo = hashValue;
            }
        }

        initLoad.setPerson(user);
        initLoad.setGoTo(goTo);
        initLoad.setErrorMessage(message);
        initLoad.setPublicCaptchaKey(publicCaptchaKey);
        initLoad.setUserRoles(userManager.getRoles());



        return initLoad;
    }

    @Override
    public List<AlternativeFundingBid> getAlternativeFundingBids(){
        /*if(!firstRound) {
            alternativeFundingBidManager.importAlternativeFundingBids();
            firstRound = true;
        }*/
        return alternativeFundingBidManager.getAllFundingBids();
    }

    @Override
    public String saveOrganization(Organization organization) throws OrganizationManagerException {
        return organizationManager.saveOrganization(organization);
    }

    @Override
    public User loginUser(String email, String password) throws PersonManagerException {
        User user = userManager.login(email, password);
        return user;
    }

    @Override
    public void resetPassword(String email) throws PersonManagerException {
        userManager.resetPassword(email);
    }

    @Override
    public void registerUser(User user, String captchaChallenge, String captchaResponse) throws Exception {

        ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
        reCaptcha.setPrivateKey(privateCaptchaKey);
        ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(hostName, captchaChallenge, captchaResponse);

        if (!reCaptchaResponse.isValid())
            throw new Exception("captcha");

        Publisher pub = user.getPublisher();
        if(pub != null){
            user.setPublisher(pub);
            if(pub.getId() == null){
                pub.getContacts().add(user);
                publisherManager.savePublisher(pub);
                userManager.register(user);
            }else{
                userManager.register(user);
                pub.getContacts().add(user);
                publisherManager.savePublisher(pub);
            }
        }else
            userManager.register(user);
    }

    @Override
    public User updateUser(User user) throws PersonManagerException {

        Publisher p = user.getPublisher();
        if(p!=null){
            p.getContacts().add(user);
            publisherManager.savePublisher(p);
        }
        return userManager.saveUser(user);
    }

    @Override
    public User getUserById(String userId) throws PersonManagerException {
        return userManager.getById(userId);
    }

    @Override
    public User getUserByEmail(String email) throws PersonManagerException{
        return userManager.getByEmail(email);
    }

    @Override
    public User saveResearcher(User user) throws PersonManagerException {
        return userManager.saveUser(user);
    }

    @Override
    public Request saveRequest(Request request) {
        return requestManager.saveRequest(request);
    }

    @Override
    public Request submitRequest(Request request) throws PersonManagerException {
        return requestManager.submitRequest(request);
    }

    @Override
    public ProjectAndEligibility getProjectInfoAndEligibility(String projectId) {

        Project project = projectManager.getById(projectId);

        ProjectAndEligibility projectInfoAndEligibility = new ProjectAndEligibility();
        projectInfoAndEligibility.setProject(project);
        Request request = new Request();
        request.setProject(project);
        request.setStatus(Request.RequestStatus.INCOMPLETE);
        projectInfoAndEligibility.setEligibility(eligibilityManager.validate(request));

        return projectInfoAndEligibility;
    }

    @Override
    public Publication savePublication(Publication publication) {

        Publication savedPublication = null;
        if(publication.getType().equals(PublicationType.ARTICLE)) {
            Journal journal = publication.getJournal();
            if (journal.getId()==null) {
                Journal savedJournal = journalManager.generateId(journal);
                savedJournal = journalManager.saveJournal(journal);
                publication.setJournal(savedJournal);
            }
            if(journal.getPublisher()!=null)
                publisherManager.savePublisher(journal.getPublisher());
            savedPublication = publicationManager.savePublication(publication);
        } else {
            Publisher publisher = publication.getPublisher();
            if(publisher.getId()==null) {
                Publisher savedPublisher = publisherManager.generateId(publisher);
                publication.setPublisher(savedPublisher);
            }
            savedPublication = publicationManager.savePublication(publication);
            publisherManager.savePublisher(publication.getPublisher());
        }
        return savedPublication;
    }

    @Override
    public Journal getJournal(String journalId) {
        return journalManager.getJournal(journalId);
    }

    @Override
    public Publisher getPublisher(String publisherId) {
        return publisherManager.getPublisher(publisherId);
    }


    @Override
    public Publication resolveDOI(String doi) throws ManagerException {
        return publicationManager.resolveDOI(doi);
    }

    @Override
    public RequestPage getRequests(Date fromDate, Date toDate, RequestSort requestSortBy, RequestSortOrder order,
                                         RequestFilter requestFilter, String term, Request.RequestStatus[] statusFilters,
                                         int from, int to) {
        return requestManager.getRequests(fromDate, toDate, requestSortBy, order, requestFilter, term, statusFilters, from, to);
    }

    @Override
    public RequestPage getRequestsForAccounting(Date fromDate, Date toDate, RequestSort requestSortBy, RequestSortOrder order,
                                         RequestFilter requestFilter, String term, Request.RequestStatus[] statusFilters,
                                         int from, int to) {
        return requestManager.getForAccounting(fromDate, toDate, requestSortBy, order, requestFilter, term, statusFilters, from, to);
    }

    @Override
    public RequestPage getRequestsForUser(String email, Date fromDate, Date toDate, RequestSort requestSortBy, RequestSortOrder order,
                                                RequestFilter requestFilter, String term, Request.RequestStatus[] statusFilters,
                                                int from, int to) {
        return requestManager.getForUser(email, fromDate, toDate, requestSortBy, order, requestFilter, term, statusFilters, from, to);
    }

    @Override
    public RequestPage getRequestsForOrganizations(List<String> organizationIds, Date fromDate, Date toDate, RequestSort requestSortBy,
                                                         RequestSortOrder order, RequestFilter requestFilter, String term,
                                                         Request.RequestStatus[] statusFilters, int from, int to) {
        return requestManager.getForOrganization(organizationIds, fromDate, toDate, requestSortBy, order, requestFilter, term, statusFilters, from, to);
    }

    @Override
    public RequestPage getRequestsForPublisher(String publisher, Date fromDate, Date toDate, RequestSort requestSortBy,
                                                     RequestSortOrder order, RequestFilter requestFilter, String term,
                                                     Request.RequestStatus[] statusFilters, int from, int to) {
        return requestManager.getForPublisher(publisher, fromDate, toDate, requestSortBy, order, requestFilter, term, statusFilters, from, to);
    }

    @Override
    public FundingWizardState getFundingWizardState(String requestId) {

        Request request = requestManager.getById(requestId);

        if(request!=null) {

            FundingWizardState fundingWizardState = new FundingWizardState();
            fundingWizardState.setRequest(request);
            fundingWizardState.setResearcher(request.getResearcher());
            fundingWizardState.setProject(request.getProject());
            fundingWizardState.setPublication(request.getPublication());
            fundingWizardState.setInvoice(request.getInvoice());

            return fundingWizardState;
        }

        return null;
    }

    @Override
    public void approveRequest(String requestId, String email, String comment, String templateId) {
        requestManager.approveRequest(requestId, email, comment, templateId);
    }

    @Override
    public void conditionalApproveRequest(String requestId, String email, String comment, String templateId) {
        requestManager.conditionallyApproveRequest(requestId, email, comment, templateId);
    }

    @Override
    public void rejectRequest(String requestId, String email, String comment, String templateId) {
        requestManager.rejectRequest(requestId, email, comment, templateId);
    }

    @Override
    public void processingRequest(String requestId, String email, String comment, String templateId) {
        requestManager.processingRequest(requestId, email, comment, templateId);
    }

    @Override
    public void onHoldRequest(String requestId, String email, String comment, String templateId) {
        requestManager.onHoldRequest(requestId, email, comment, templateId);
    }

    @Override
    public void deniedRequest(String requestId, String email, String comment, String templateId) {
        requestManager.deniedRequest(requestId, email, comment, templateId);
    }

    @Override
    public void paidLibraryRequest(String requestId, String email, String comment, String template, float apc_paid, float transfer_cost, float other_cost, Date datePaid) {
        requestManager.paidLibraryRequest(requestId, email, comment, template, apc_paid, transfer_cost, other_cost, datePaid);
    }

    @Override
    public void paidPublisherRequest(String requestId, String email, String comment, String template, float apc_paid, float transfer_cost, float other_cost, Date datePaid) {
        requestManager.paidPublisherRequest(requestId, email, comment, template, apc_paid, transfer_cost, other_cost, datePaid);
    }

    @Override
    public Request getRequestById(String requestId) {
        return requestManager.getById(requestId);
    }

    @Override
    public void submitContactForm(Contact contact, String captchaChallenge, String captchaResponse) throws Exception {

        ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
        reCaptcha.setPrivateKey(privateCaptchaKey);
        ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(hostName, captchaChallenge, captchaResponse);

        if (!reCaptchaResponse.isValid())
        	throw new Exception("captcha");

        contactManager.submitContact(contact);
    }

    @Override
    public List<User> getUsers() {
        return userManager.getUsers();
    }

    @Override
    public void activateUser(String email) {
        userManager.activateUser(email);
    }

    @Override
    public void activateUsers(List<String> emails) {
        userManager.activateUsers(emails);
    }

    @Override
    public void deactivateUser(String email) {
        userManager.deactivateUser(email);
    }

    @Override
    public void deactivateUsers(List<String> emails) {
        userManager.deactivateUsers(emails);
    }

    @Override
    public void acceptUserRole(String email, String roleId) {
        userManager.acceptUserRole(email, roleId);
    }

    @Override
    public void rejectRole(String email, String roleId) {
        userManager.rejectRole(email, roleId);
    }

    @Override
    public Budget submitBudgetRequest(Budget budget) {
        return budgetManager.submitBudgetRequest(budget);
    }

    @Override
    public Budget saveBudget(Budget budget) {
        return budgetManager.saveBudget(budget);
    }

    @Override
    public Budget getBudgetById(String budgetId) {
        return budgetManager.getBudget(budgetId);
    }

    @Override
    public List<Budget> getBudgets() {
        return budgetManager.getBudgets();
    }

    @Override
    public List<Budget> getBudgetsForUser(String email) {
        return budgetManager.getBudgetsForUser(email);
    }

    @Override
    public List<Budget> getBudgetsForOrganizations(List<String> organizationIds) {
        return budgetManager.getBudgetsForOrganization(organizationIds);
    }


    @Override
    public void initiallyApproveBudgetRequest(String budgetId, String comment, String personId) {
        budgetManager.initiallyApproveBudgetRequest(budgetId, comment, personId);
    }

    @Override
    public void approveBudgetRequest(String budgetId, String comment, float amountGranted, String personId) {
        budgetManager.approveBudgetRequest(budgetId, comment, amountGranted, personId);
    }

    @Override
    public void rejectBudgetRequest(String budgetId, String comment, String personId) {
        budgetManager.rejectBudgetRequest(budgetId, comment, personId);
    }

    @Override
    public void processingPayment(String budgetId, String comment, String personId) {
        budgetManager.processingPayment(budgetId, comment, personId);
    }

    @Override
    public void denyPayment(String budgetId, String comment, String personId) {
        budgetManager.denyPayment(budgetId, comment, personId);
    }

    @Override
    public void onHoldPayment(String budgetId, String comment, String personId) {
        budgetManager.onHoldPayment(budgetId, comment, personId);
    }

    @Override
    public void budgetPaid(String budgetId, String comment, String personId) {
        budgetManager.budgetPaid(budgetId, comment, personId);
    }

    @Override
    public EligiblePresentAndFutureProjects getEligibleProjectsForOrganization(String organizationId) {

        EligiblePresentAndFutureProjects eligiblePresentAndFutureProjects = new EligiblePresentAndFutureProjects();
        eligiblePresentAndFutureProjects.setPresentEligibleProjects(projectManager.getEligibleProjectsForOrganization(organizationId));
        eligiblePresentAndFutureProjects.setFutureEligibleProjects(projectManager.getFutureEligibleProjectsForOrganization(organizationId));

        return eligiblePresentAndFutureProjects;
    }

    @Override
    public Help saveHelp(Help help) {
        return helpManager.saveHelp(help);
    }

    @Override
    public Help getHelpById(String id) {

        Help help = helpManager.getById(id);
        System.out.println("Help text " + help.getText());
        return help;
    }

    @Override
    public Invoice invoiceUploaded(String requestId, String invoiceId) throws ManagerException {
        return requestManager.invoiceUploaded(requestId, invoiceId);
    }

    @Override
    public float convert(Currency from, Currency to, float amount) {
        return currencyConverter.convert(from, to, amount);
    }

    @Override
    public StatsData getStatsData() {

        StatsData statsData = new StatsData();

        statsData.setNumbers(statsManager.getNumbers(new Numbers.Category[]{Numbers.Category.REQUESTS, Numbers.Category.PROJECTS,
                Numbers.Category.TOTAL_AMOUNT, Numbers.Category.AVERAGE_AMOUNT, Numbers.Category.AVERAGE_PER_ARTICLE,
                Numbers.Category.AVERAGE_PER_MONOGRAPH, Numbers.Category.AVERAGE_PER_BOOK_CHAPTER, Numbers.Category.PAID_REQUESTS,
                Numbers.Category.PAID_REQUESTS_WITH_DOI, Numbers.Category.APPROVED_REQUESTS_WITH_DOI, Numbers.Category.PAID_ARTICLE_REQUESTS,
                Numbers.Category.PAID_MONOGRAPH_REQUESTS, Numbers.Category.PAID_BOOK_CHAPTER_REQUESTS}));

        Series fundedRequests = statsManager.getSeries(new Series.Category[] {Series.Category.COUNTRY, Series.Category.ORGANIZATION,
                Series.Category.PUBLISHER}, new Request.RequestStatus[] {Request.RequestStatus.CONDITIONALLY_APPROVED,
                Request.RequestStatus.APPROVED, Request.RequestStatus.ACCOUNTING_PROCESSING, Request.RequestStatus.ACCOUNTING_PAID,
                Request.RequestStatus.ACCOUNTING_ON_HOLD});
        Series rejectedRequests = statsManager.getSeries(new Series.Category[] {Series.Category.COUNTRY, Series.Category.ORGANIZATION,
                Series.Category.PUBLISHER}, new Request.RequestStatus[] {Request.RequestStatus.REJECTED,
                Request.RequestStatus.ACCOUNTING_DENIED});


        // Countries
        extractInfo(statsData, fundedRequests, rejectedRequests, Series.Category.COUNTRY);

        // Publishers
        extractInfo(statsData, fundedRequests, rejectedRequests, Series.Category.PUBLISHER);

        // Organisations
        extractInfo(statsData, fundedRequests, rejectedRequests, Series.Category.ORGANIZATION);

        //Date Series
        statsData.setBrowse(statsManager.browse(new Browse.Category[] {Browse.Category.COUNTRY, Browse.Category.ORGANIZATION,
                Browse.Category.PUBLISHER, Browse.Category.SCIENTIFIC_AREA}));
        log.debug("After date series");
        //get funding requests and amount funded per day for the whole pilot duration
        statsData.setDateSeriesData(getDateSeriesData(DateSeries.Over.DAY, null, null, null, null, null, null));
        log.debug("After over day series");
        Series statusDistributionSeries = statsManager.getSeries(new Series.Category[] {Series.Category.STATUS}, null);
        statsData.setStatusesDistribution(statusDistributionSeries.getData(Series.Category.STATUS));

        Series publicationTypeDistributionSeries = statsManager.getSeries(new Series.Category[] {Series.Category.PUBLICATION_TYPE},
                new Request.RequestStatus[] {Request.RequestStatus.CONDITIONALLY_APPROVED, Request.RequestStatus.APPROVED,
                        Request.RequestStatus.ACCOUNTING_PROCESSING, Request.RequestStatus.ACCOUNTING_PAID, Request.RequestStatus.ACCOUNTING_ON_HOLD});
        statsData.setPublicationTypeDistribution(publicationTypeDistributionSeries.getData(Series.Category.PUBLICATION_TYPE));

        return statsData;
    }

    @Override
    public DateSeriesData getDateSeriesData(DateSeries.Over over, Date from, Date to, String[] publishers, String[] organizations, String[] countries, String[] scientificAreas) {

        DateSeriesData dateSeriesData = new DateSeriesData();
        dateSeriesData.setNewRequestsDateSeries(statsManager.getDateSeries(over, false, from, to, publishers, organizations, countries, scientificAreas));
        dateSeriesData.setCumulativeRequestsDateSeries(statsManager.getDateSeries(over, true, from, to, publishers, organizations, countries, scientificAreas));

        return dateSeriesData;
    }

    @Override
    public List<CommentTemplate> getCommentTemplates(Request.RequestStatus requestStatus) {
        return requestManager.getCommentTemplates(requestStatus);
    }

    private void extractInfo(StatsData statsData, Series fundedRequests, Series rejectedRequests, Series.Category category) {

        Map<String, Tuple<Integer, Integer>> requestsMap = new HashMap<>();
        Map<String, Tuple<Float, Float>> amountMap = new HashMap<>();

        List<Triple<String, Integer, Integer>> requestsPerCategory = new ArrayList<>();
        List<Triple<String, Float, Float>> funds = new ArrayList<>();
        List<Quintuple<String, Integer, Integer, Float, Float>> fullInfo = new ArrayList<>();

        for(Quadruple<String, Integer, Float, Float> quadruple : fundedRequests.getData(category)) {
            requestsMap.put(quadruple.getFirst(), new Tuple<Integer, Integer>(quadruple.getSecond(), 0));
            amountMap.put(quadruple.getFirst(), new Tuple<Float, Float>(quadruple.getThird(), quadruple.getFourth()));
            funds.add(new Triple<String, Float, Float>(quadruple.getFirst(), quadruple.getThird(), quadruple.getFourth()));
        }

        for(Quadruple<String, Integer, Float, Float> quadruple: rejectedRequests.getData(category)) {
            if(!requestsMap.containsKey(quadruple.getFirst())) {
                requestsMap.put(quadruple.getFirst(), new Tuple<Integer, Integer>(0, quadruple.getSecond()));
            } else {
                Tuple<Integer, Integer> existingTuple = requestsMap.get(quadruple.getFirst());
                existingTuple.setSecond(quadruple.getSecond());
                requestsMap.put(quadruple.getFirst(), existingTuple);
            }
        }

        for(String country : requestsMap.keySet()) {

            Triple<String, Integer, Integer> categoryRequests = new Triple<>(country, requestsMap.get(country).getFirst(),
                    requestsMap.get(country).getSecond());
            requestsPerCategory.add(categoryRequests);

            Float amountPaid = 0.0f;
            Float avgAmountPaid = 0.0f;
            if(amountMap.get(country)!=null && amountMap.get(country).getFirst()!=null && amountMap.get(country).getSecond()!=null) {
                amountPaid = amountMap.get(country).getFirst();
                avgAmountPaid = amountMap.get(country).getSecond();
            }

            Quintuple<String, Integer, Integer, Float, Float> categoryFullInfo =
                    new Quintuple<>(country, requestsMap.get(country).getFirst(),
                    requestsMap.get(country).getSecond(), amountPaid, avgAmountPaid);
            fullInfo.add(categoryFullInfo);
        }

        Collections.sort(requestsPerCategory, new Comparator<Triple<String, Integer, Integer>>() {
            @Override
            public int compare(Triple<String, Integer, Integer> o1, Triple<String, Integer, Integer> o2) {
                return -(o1.getSecond()).compareTo(o2.getSecond());
            }
        });

        Collections.sort(funds, new Comparator<Tuple<String, Float>>() {
            @Override
            public int compare(Tuple<String, Float> o1, Tuple<String, Float> o2) {
                return -(o1.getSecond()).compareTo(o2.getSecond());
            }
        });

        if(category.equals(Series.Category.COUNTRY)) {

            statsData.setRequestsPerCountry(requestsPerCategory);
            statsData.setFundsPerCountry(funds);
            statsData.setCountriesFullInfo(fullInfo);

        } else if(category.equals(Series.Category.ORGANIZATION)) {

            statsData.setRequestsPerOrganisation(requestsPerCategory);
            statsData.setFundsPerOrganisation(funds);
            statsData.setOrganisationsFullInfo(fullInfo);

        } else if(category.equals(Series.Category.PUBLISHER)) {

            statsData.setRequestsPerPublisher(requestsPerCategory);
            statsData.setFundsPerPublisher(funds);
            statsData.setPublishersFullInfo(fullInfo);
        }
    }

    @Override
    public  Organization getOrganization(String organizationId) throws OrganizationManagerException {
        return organizationManager.getById(organizationId);
    }

    @Override
    public Project getProject(String projectId){
        return projectManager.getById(projectId);
    }

    @Override
    public List<Object> getFundingBidDocuments(String id) throws Exception {
        return alternativeFundingBidManager.getDocuments(id);
    }


    @Override
    protected SerializationPolicy doGetSerializationPolicy(HttpServletRequest request, String moduleBaseURL, String strongName) {
        return super.doGetSerializationPolicy(request, "http://localhost:8380/goldoa/GoldOAPortal/", strongName);
    }

}
