package org.exoplatform.cs.rest.utils;


import org.apache.commons.lang3.StringUtils;
import org.exoplatform.commons.utils.CommonsUtils;
import org.exoplatform.cs.dto.*;
import org.exoplatform.cs.rest.model.CSEnvironment;
import org.exoplatform.cs.rest.model.CSpace;
import org.exoplatform.cs.rest.model.Ticket;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.task.service.TaskService;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class EntityBuilder {

    private static SimpleDateFormat simpleCreatedTicketDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss");
    private static SimpleDateFormat simpleUpdateEnvDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss");

    private static final Log LOG = ExoLogger.getLogger(EntityBuilder.class);

    public static final Ticket fromTicketDto(TicketDTO ticketDTO) {
        return new Ticket(ticketDTO.getId(), ticketDTO.getTitle(), ticketDTO.getStatus(), ticketDTO.getDescription(),
                ticketDTO.getLink(), ticketDTO.getAssignee(), ticketDTO.getAssigneeAvatar(), ticketDTO.getTagName(), ticketDTO.getType(),
                ticketDTO.getSeverity(), ticketDTO.getInfoType(), ticketDTO.getSpaceGroupId(),
                ticketDTO.getEnvironmentName(), ticketDTO.getEnvironmentId(),
                fromCalendar((ticketDTO.getStartDate().getTime()), simpleCreatedTicketDateFormat), ticketDTO.getFlow(),
                ticketDTO.getTicketId(), ticketDTO.getCreator(), ticketDTO.getCreatorId(), ticketDTO.getCreatorAvatar(),
                ticketDTO.getOwner(), ticketDTO.getAttachedJira(), ticketDTO.getWarning(), ticketDTO.getJiraStatus(),
                ticketDTO.getJiraStatusIcon(), ticketDTO.getTimeToFirstResponse(),
                ticketDTO.getTimeToResolution(), ticketDTO.getCustomerSatisfied(), ticketDTO.getInternal(),
                ticketDTO.getActive(), ticketDTO.getReason(), ticketDTO.getRateReason(), ticketDTO.getUploads(), getTicketTypes(),
                getOwnersList(), getSeverities(ticketDTO.getType()), getTicketAttachedTasksStatus(ticketDTO.getAttachedJira()));
    }

    public static final TicketDTO toTicketDto(Ticket ticket) throws ParseException {
        TicketDTO ticketDTO = new TicketDTO();
        ticketDTO.setId(ticket.getId());
        ticketDTO.setTitle(ticket.getTitle());
        ticketDTO.setStatus(ticket.getStatus());
        ticketDTO.setDescription(ticket.getDescription());
        ticketDTO.setLink(ticket.getLink());
        ticketDTO.setAssignee(ticket.getAssignee());
        ticketDTO.setTagName(ticket.getTagName());
        ticketDTO.setType(ticket.getType());
        ticketDTO.setSpaceGroupId(ticket.getSpaceGroupId());
        ticketDTO.setEnvironmentName(ticket.getEnvironmentName());
        ticketDTO.setEnvironmentId(ticket.getEnvironmentId());
        ticketDTO.setFlow(ticket.getFlow());
        ticketDTO.setTicketId(ticket.getTicketId());
        ticketDTO.setCreator(ticket.getCreator());
        ticketDTO.setOwner(ticket.getOwner());
        ticketDTO.setSeverity(ticket.getSeverity());
        ticketDTO.setStartDate(toCalendar(ticket.getStartDate(), simpleCreatedTicketDateFormat));
        ticketDTO.setAttachedJira(ticket.getAttachedJira());
        ticketDTO.setWarning(ticket.getWarning());
        ticketDTO.setJiraStatus(ticket.getJiraStatus());
        ticketDTO.setJiraStatusIcon(ticket.getJiraStatusIcon());
        ticketDTO.setTimeToFirstResponse(ticket.getTimeToFirstResponse());
        ticketDTO.setTimeToResolution(ticket.getTimeToResolution());
        ticketDTO.setCustomerSatisfied(ticket.getCustomerSatisfied());
        ticketDTO.setInternal(ticket.getInternal());
        ticketDTO.setActive(ticket.getActive());
        ticketDTO.setReason(ticket.getReason());
        ticketDTO.setRateReason(ticket.getRateReason());
        ticketDTO.setUploads(ticket.getUploads());

        return ticketDTO;
    }

    public static final CSEnvironment fromEnvironmentDto(EnvironmentDTO environmentDTO) {
        return new CSEnvironment(environmentDTO.getId(), environmentDTO.getName(), environmentDTO.getSpaceGroupId(),
                environmentDTO.isDefaultEnvironment(), environmentDTO.getTypeId(), environmentDTO.getTypeName(), environmentDTO.getTypeOtherId(),
                environmentDTO.getTypeOtherName(), environmentDTO.getProductVersion(), environmentDTO.getOsId(), environmentDTO.getOsName(),
                environmentDTO.getOsOtherId(), environmentDTO.getOsOtherName(), environmentDTO.getOsVersion(), environmentDTO.getJvmVendorId(),
                environmentDTO.getJvmVendorName(), environmentDTO.getJvmVendorOtherId(), environmentDTO.getJvmVendorOtherName(), environmentDTO.getJvmVersion(),
                environmentDTO.getAsId(), environmentDTO.getAsName(), environmentDTO.getAsOtherId(), environmentDTO.getAsOtherName(), environmentDTO.getAsVersion(),
                environmentDTO.getDbId(), environmentDTO.getDbName(), environmentDTO.getDbOtherId(), environmentDTO.getDbOtherName(),
                environmentDTO.getDbVersion(), environmentDTO.getDbEncoding(), environmentDTO.getSsoId(), environmentDTO.getSsoName(),
                environmentDTO.getSsoOtherId(), environmentDTO.getSsoOtherName(), environmentDTO.getSsoVersion(), environmentDTO.getMoreInformation(),
                environmentDTO.getBrowsers(), fromCalendar(environmentDTO.getUpdateDate().getTime(), simpleUpdateEnvDateFormat), environmentDTO.getCustomerExtensionVersion(),
                environmentDTO.getInstalledPatchVersion());
    }

    public static final CSpace fromSpaceDto(SpaceDTO spaceDTO) {
        return new CSpace(spaceDTO.getName(), spaceDTO.getDescription(), spaceDTO.getGroupId(), spaceDTO.getUrl(),
                spaceDTO.getTaskDefaultAssignee(), spaceDTO.getTagPrefix(),
                spaceDTO.getManagersGroupId(), spaceDTO.getInvitedMembersGroupId(), spaceDTO.getMembers(),
                spaceDTO.getTagIndex(), spaceDTO.getTaskPriority(), spaceDTO.getOwner(),
                spaceDTO.getLimitTicketsNumber(), spaceDTO.getSupportTickets(), spaceDTO.getActifTickets(),
                spaceDTO.getProductTickets(), spaceDTO.getTotalTickets(), spaceDTO.getIncidentFlow(),
                spaceDTO.getInformationFlow(), spaceDTO.getLanguage(), spaceDTO.isHosted(), spaceDTO.getSla(),
                spaceDTO.getSubscription(), spaceDTO.getSubscriptionStartDate(), spaceDTO.getSubscriptionEndDate(),
                spaceDTO.isSubscriptionActive(), spaceDTO.isInternal(), spaceDTO.getCustomerExtensionVersion(),
                spaceDTO.getInstalledPatchVersion(), "");
    }

    private static List<String> getSeverities(IssueType ticketType) {
        List<String> severities = new ArrayList<>();
        if(ticketType.equals(IssueType.INCIDENT)){
            severities.add(IssueSeverity.SEVERITY_1.name());
            severities.add(IssueSeverity.SEVERITY_2.name());
            severities.add(IssueSeverity.SEVERITY_3.name());
        } else if(ticketType.equals(IssueType.INFORMATION)) {
            severities.add(IssueSeverity.SEVERITY_4.name());
        }
        return severities;
    }

    private static List<String> getTicketTypes() {
        List<String> ticketTypes = new ArrayList<>();
        ticketTypes.add(IssueType.INCIDENT.name());
        ticketTypes.add(IssueType.INFORMATION.name());
        return ticketTypes;
    }

    private static List<String> getOwnersList() {
        List<String> ownersList = new ArrayList<>();
        Owner[] owners = Owner.values();
        for (int i=0; i<owners.length; i++ ){
            ownersList.add(owners[i].name());
        }
        return ownersList;
    }
    private static String fromCalendar(Date date, SimpleDateFormat simpleDateFormat) {
        return simpleDateFormat.format(date);
    }
    private static Calendar toCalendar(String date, SimpleDateFormat simpleDateFormat) throws ParseException {
        Date calendarDate = simpleDateFormat.parse(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(calendarDate);
        return calendar;
    }

    private static Map<String, String> getTicketAttachedTasksStatus (String tasks){
        Map<String, String> result = new HashMap<>();
        TaskService taskService = CommonsUtils.getService(TaskService.class);
        if (StringUtils.isNotBlank(tasks)) {
            Arrays.stream(tasks.split("\\s+"))
                    .filter(taskId -> StringUtils.isNumeric(taskId))
                    .mapToLong(Long::parseLong)
                    .forEach(taskId -> {
                        String status = "";
                        try {
                            status = taskService.getTask(taskId).getStatus().getName();
                        } catch (Exception e) {
                            LOG.warn("Could not get ticket attached task status");
                        }
                        result.put(Long.toString(taskId), status);
                    });
        }
        return result;
    }
}
