/*
 *
 *  * Copyright (C) 2003-2016 eXo Platform SAS.
 *  *
 *  * This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Affero General Public License
 *  as published by the Free Software Foundation; either version 3
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, see<http://www.gnu.org/licenses/>.
 *
 */
package org.exoplatform.cs.service;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.StringUtils;
import org.exoplatform.commons.api.persistence.ExoTransactional;
import org.exoplatform.commons.utils.HTMLSanitizer;
import org.exoplatform.cs.dao.EnvironmentDAO;
import org.exoplatform.cs.dao.LogDAO;
import org.exoplatform.cs.dao.SpaceDAO;
import org.exoplatform.cs.dao.TopicDAO;
import org.exoplatform.cs.dto.BasicEntityDTO;
import org.exoplatform.cs.dto.EnvironmentDTO;
import org.exoplatform.cs.dto.IssueType;
import org.exoplatform.cs.dto.LogType;
import org.exoplatform.cs.dto.SpaceDTO;
import org.exoplatform.cs.dto.TicketDTO;
import org.exoplatform.cs.entity.EnvironmentEntity;
import org.exoplatform.cs.entity.LogEntity;
import org.exoplatform.cs.entity.SpaceEntity;
import org.exoplatform.cs.entity.TopicEntity;
import org.exoplatform.cs.service.tickets.TicketStatusFlowService;
import org.exoplatform.cs.service.util.ForumUtils;
import org.exoplatform.forum.common.CommonUtils;
import org.exoplatform.forum.service.*;
import org.exoplatform.forum.service.filter.model.ForumFilter;
import org.exoplatform.services.listener.ListenerService;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.security.Identity;
import org.exoplatform.social.core.space.SpaceUtils;
import org.exoplatform.task.domain.Project;
import org.exoplatform.task.domain.Status;
import org.exoplatform.task.domain.Task;
import org.exoplatform.task.exception.EntityNotFoundException;
import org.exoplatform.task.service.ProjectService;
import org.exoplatform.task.service.StatusService;
import org.exoplatform.task.service.TaskService;
import org.exoplatform.task.util.ProjectUtil;
import org.exoplatform.task.util.TaskUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.ItemExistsException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by The eXo Platform SAS
 *
 * @author boubaker.khanfir@exoplatform.com
 * @since Apr 27, 2016
 */
public class TicketService extends BaseService {
  private static final Logger LOG = LoggerFactory.getLogger(TicketService.class);

  private TaskService         taskService;

  private ForumService        forumService;

  private ProjectService      projectService;

  private StatusService       statusService;

  private ListenerService listenerService;

  private static final String DATE_FORMAT_DISPLAYED_IN_TICKETS_LIST = "yyyy-MM-dd HH:mm:ss";

  private static final String TOPIC_DEFAULT_DATE_FORMAT = "EE MMM dd HH:mm:ss z yyyy";
  

  private static final String TASK_DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";

  private static final DateFormat   DATE_FORMAT_TO_CONVERT_USED_FOR_TICKETS = new SimpleDateFormat(DATE_FORMAT_DISPLAYED_IN_TICKETS_LIST);

  private static final DateFormat   DEFAULT_DATE_FORMAT_USED_FOR_TOPICS = new SimpleDateFormat(TOPIC_DEFAULT_DATE_FORMAT);

  private static final DateFormat DEFAULT_DATE_FORMAT_USED_FOR_TASKS = new SimpleDateFormat(TASK_DEFAULT_DATE_FORMAT);
  private static final DateFormat DATE_FORMAT_USED_FOR_TASKS = new SimpleDateFormat(TASK_DEFAULT_DATE_FORMAT);

  public TicketService(ForumService forumService,
                       ListenerService listenerService,
                       ProjectService projectService,
                       StatusService statusService,
                       TaskService taskService,
                       EnvironmentDAO environmentDAO,
                       SpaceDAO spaceDAO,
                       TopicDAO topicDAO) {
    super(environmentDAO, spaceDAO, topicDAO, null);
    this.taskService = taskService;
    this.forumService = forumService;
    this.statusService = statusService;
    this.projectService = projectService;
    this.listenerService = listenerService;
  }

  public EnvironmentDTO getTopicEnvironment(String topicId) {
    if (StringUtils.isBlank(topicId)) {
      throw new IllegalStateException("Parameter 'topicId' is null");
    }
    TopicEntity topicEntity = topicDAO.find(topicId);
    if (topicEntity.getEnvironment() == null) {
      return null;
    }
    return convert(topicEntity.getEnvironment());
  }

  public List<TicketDTO> getTicketsOfSpace(String id) {
    List<TopicEntity> entities = topicDAO.getTopicsBySpace(id);
    SpaceEntity space = spaceDAO.find(id);
    List<TicketDTO> tickets = new ArrayList<TicketDTO>();
    for (TopicEntity topicEntity : entities) {
      tickets.add(convertToDTO(topicEntity, space));
    }
    return tickets;
  }

  public List<TicketDTO> getTickets(String selectedSpace, boolean allTickets) {
    List<TopicEntity> entities;
    if(allTickets) {
      if(selectedSpace != null && !selectedSpace.isEmpty()) {
        entities = topicDAO.getTopicsBySpace(selectedSpace);
      } else {
        entities = topicDAO.findAll();
      }
    } else {
      if(selectedSpace != null && !selectedSpace.isEmpty()) {
        entities = topicDAO.getOpenTicketsBySpace(selectedSpace);
      } else {
        entities = topicDAO.getOpenTickets();
      }
    }
    return convertToDTO(entities);
  }

  public List<TicketDTO> getAssignedTickets(String assignee, String selectedSpace, boolean allTickets){
    List<TopicEntity> tickets = new ArrayList<>();
    if(selectedSpace != null && !selectedSpace.isEmpty()){
      tickets = topicDAO.getTopicsByAssignee(assignee, selectedSpace, allTickets);
    }else {
      tickets = topicDAO.getTopicsByAssignee(assignee, allTickets);
    }
    return convertToDTO(tickets);
  }

  public String getManagersGroupId(String spaceGroupId) throws Exception {
    SpaceEntity space = spaceDAO.find(spaceGroupId);
    return space.getManagersGroupId();
  }

  public SpaceEntity getSpaceByGroupId(String  groupID) {
    return spaceDAO.find(groupID);
  }

  /** Update Ticket
   *  @param ticketDTO the customer ticket
   *  @param user The user who updated the ticket
   *  @throws Exception if broadcasting the event failed
   *  @return TicketDTO updated
   *
   */
  public TicketDTO updateTicket(TicketDTO ticketDTO, User user) throws Exception {
    //TODO Why do we need an entity as a parameter here
    Map<String,String> changes = new HashMap<>();
    TopicEntity topicEntity = topicDAO.find(ticketDTO.getId());
    EnvironmentEntity environment = null;
    if (ticketDTO.getAssignee() != null && !(ticketDTO.getAssignee().equals(topicEntity.getAssignee()))) {
      changes.put(CSConstants.OLD_ASSIGNEE,topicEntity.getAssignee());
      changes.put(CSConstants.NEW_ASSIGNEE,ticketDTO.getAssignee());
    }
    if(!IssueType.PRODUCT.equals(ticketDTO.getType())) {
      String oldSeverity = null, oldType = null;
      if (!(ticketDTO.getSeverity().equals(topicEntity.getSeverity()))) {
        oldSeverity = topicEntity.getSeverity().name();
        changes.put(CSConstants.OLD_SEVERITY,oldSeverity);
        changes.put(CSConstants.NEW_SEVERITY,ticketDTO.getSeverity().name());
      }
      if (!(ticketDTO.getType().equals(topicEntity.getType()))) {
        oldType = topicEntity.getType().name();
        changes.put(CSConstants.OLD_TYPE,oldType);
        changes.put(CSConstants.NEW_TYPE,ticketDTO.getType().name());
      }
      if (!(ticketDTO.getStatus().equals(topicEntity.getStatus()))) {
        oldType = topicEntity.getType().name();
        changes.put(CSConstants.OLD_STATUS,topicEntity.getStatus());
        changes.put(CSConstants.NEW_STATUS,ticketDTO.getStatus());
      }
      try {
        Category spaceCategory = forumService.getCategoryIncludedSpace();
        Forum forum = ForumUtils.getSpaceForum(forumService,ticketDTO.getSpaceGroupId());
        Topic topic = forumService.getTopic(spaceCategory.getId(), forum.getId(), topicEntity.getId(), null);
        updateForumTags(ticketDTO, topic, oldSeverity, oldType);
      } catch (Exception e) {
        LOG.error("Could not update topic {} with tags", topicEntity.getLink(), e);
      }
      if (ticketDTO.getEnvironmentId() != null) {
        environment = environmentDAO.find(ticketDTO.getEnvironmentId());
      }
    }
    changes.put(CSConstants.USERID, user.getUserName());

    convertToEntity(ticketDTO, topicEntity, environment);
    topicEntity.setUpdateDate(Calendar.getInstance());
    topicDAO.update(topicEntity);
    listenerService.broadcast(CSConstants.TICKET_UPDATED,topicEntity,changes);
    SpaceEntity spaceEntity = spaceDAO.find(ticketDTO.getSpaceGroupId());
    return convertToDTO(topicEntity, spaceEntity);
  }

  /**
   * Update the link on the entity
   * @param ticket the ticket to update
   * @param link the link of the ticket
   */
  public void updateTicketLink(TicketDTO ticket, String link){
    TopicEntity entity = topicDAO.find(ticket.getId());
    entity.setLink(link);
    topicDAO.update(entity);
  }

  @ExoTransactional
  public void createTicket(TicketDTO ticketDTO, User user) throws Exception {
    if (user == null) {
      throw new IllegalArgumentException("Method saveUser - argument user is null");
    }
    String email = user.getEmail();
    if (StringUtils.isBlank(email)) {
      throw new IllegalArgumentException("Method saveUser - argument user.email is null");
    }
    if (ticketDTO == null) {
      throw new IllegalArgumentException("Method saveUser - argument ticketDTO is null");
    }
    if (!ticketDTO.verifySaveConditions()) {
      throw new IllegalArgumentException("Method saveUser - argument ticketDTO is not conform: " + ticketDTO);
    }

    SpaceEntity spaceEntity = spaceDAO.find(ticketDTO.getSpaceGroupId());
    if (spaceEntity == null) {
      throw new IllegalStateException("Method saveUser - Space is not found");
    }

    Date currentDate = CommonUtils.getGreenwichMeanTime().getTime();
    long tagIndex = spaceEntity.getTagIndex();
    TopicEntity topicEntity = new TopicEntity();

    if (IssueType.PRODUCT.equals(ticketDTO.getType())) {
      Task task = new Task();
      task.setDescription(ticketDTO.getDescription());
      task.setTitle(ticketDTO.getTitle());
      task.setAssignee(spaceEntity.getTaskDefaultAssignee());
      ticketDTO.setAssignee(spaceEntity.getTaskDefaultAssignee());
      task.setCreatedBy(user.getUserName());
      task.setPriority(spaceEntity.getTaskPriority());
      task.setCreatedTime(currentDate);
      Date startDate = ticketDTO.retrieveFormattedStartDate();
      task.setStartDate(startDate);
      Date endDate = ticketDTO.retrieveFormattedEndDate();
      task.setEndDate(endDate);
      task.setDueDate(endDate);

      Status status = getSpaceProjectStatus(ticketDTO.getSpaceGroupId(), user.getUserName());
      task.setStatus(status);
      task = taskService.createTask(task);

      ticketDTO.setId("" + task.getId());
      String ticketDateTask = convertDate(DEFAULT_DATE_FORMAT_USED_FOR_TASKS, task.getCreatedTime().toString());
      ticketDTO.setStartDate(ticketDateTask);
      String space = ForumUtils.getSpaceForum(forumService,spaceEntity.getGroupId()).getForumName();
      String SpaceName = SpaceUtils.cleanString(space);
      String taskLink = "/portal/g/:spaces:" + SpaceName + "/" + SpaceName + "/tasks" + TaskUtil.URL_TASK_DETAIL + task.getId();
      ticketDTO.setLink(taskLink);
      convertToEntity(ticketDTO, topicEntity, null);
      topicDAO.create(topicEntity);
      Map<String,String> data = new HashMap<>();
      data.put(CSConstants.USERID,user.getUserName());
      listenerService.broadcast(CSConstants.TICKET_CREATED,topicEntity,data);
    } else if (IssueType.INCIDENT.equals(ticketDTO.getType()) || IssueType.INFORMATION.equals(ticketDTO.getType())) {
      Topic newTopic = new Topic();
      if (IssueType.INCIDENT.equals(ticketDTO.getType())) {
        newTopic.setTopicName(HTMLSanitizer.sanitize("[" + spaceEntity.getTagPrefix() + "-" + tagIndex + "] " + ticketDTO.getTitle()));
        List<FileItem> files = ticketDTO.getFiles();
        if (files != null && !files.isEmpty()) {
          List<ForumAttachment> forumAttachments = new ArrayList<ForumAttachment>();
          for (final FileItem fileItem : files) {
            ForumAttachment attachment = new BufferAttachment() {
              private static final long serialVersionUID = 1221108176051647731L;

              @Override
              public InputStream getInputStream() throws Exception {
                return fileItem.getInputStream();
              }
            };
            attachment.setName(fileItem.getName());
            attachment.setMimeType(fileItem.getContentType());
            forumAttachments.add(attachment);
          }
          newTopic.setAttachments(forumAttachments);
        }
      } else if (IssueType.INFORMATION.equals(ticketDTO.getType())) {
        newTopic.setTopicName(HTMLSanitizer.sanitize("[" + spaceEntity.getTagPrefix() + "-" + tagIndex + "] " + ticketDTO.getTitle()));
      } else {
        LOG.warn("Unrecognized ticket type {}, set default title without prefixes.", ticketDTO.getType());
        newTopic.setTopicName("[" + spaceEntity.getTagPrefix() + "-" + tagIndex + "] "+ticketDTO.getTitle());
      }

      Category spaceCategory = forumService.getCategoryIncludedSpace();
      if (spaceCategory == null) {
        throw new IllegalStateException("Cannot find Forum Spaces category.");
      }
      String groupId = spaceEntity.getGroupId();

      Forum spaceForum = ForumUtils.getSpaceForum(forumService, groupId);

      String link = ForumUtils.createdForumLink(ForumUtils.TOPIC, newTopic.getId(), false);
      link = link.replace("/ticket", "/forum");
      ticketDTO.setLink(link);

      newTopic.setModifiedBy(user.getUserName());
      newTopic.setModifiedDate(currentDate);
      // encode XSS script
      String message = HTMLSanitizer.sanitize(ticketDTO.getDescription());
      newTopic.setDescription(message);
      newTopic.setLink(link);
      newTopic.setIsNotifyWhenAddPost(email);
      newTopic.setIsWaiting(false);
      newTopic.setIsClosed(false);
      newTopic.setIsLock(false);
      newTopic.setIsModeratePost(false);
      newTopic.setIsSticky(false);
      newTopic.setIcon("");
      newTopic.setOwner(user.getUserName());

      // TODO, do we need a specific icon ?
      // newTopic.setIcon("uiIconForumTopic uiIconForumLightGray");

      // Save Topic
      forumService.saveTopic(spaceCategory.getId(), spaceForum.getId(), newTopic, true, false, new MessageBuilder());
      updateForumTags(ticketDTO,newTopic,null,null);

      // Save entity
      EnvironmentEntity environmentEntity = null;
      if (ticketDTO.getType().equals(IssueType.INCIDENT)) {
        environmentEntity = environmentDAO.find(ticketDTO.getEnvironmentId());
        if (environmentEntity == null) {
          throw new IllegalStateException("Environment with id '" + ticketDTO.getEnvironmentId() + "' is null");
        } else if (environmentEntity.getSpace() == null) {
          // The space is mandatory field, but in case the model has evolved,
          // handle
          // this
          throw new IllegalStateException("Environment's space is null");
        }
      }
      // Increment Tag index
      spaceEntity.setTagIndex(tagIndex + 1);
      spaceDAO.update(spaceEntity);

      // Save ticket
      ticketDTO.setId(newTopic.getId());
      ticketDTO.setStatus(CSConstants.STATUS_OPEN);
      ticketDTO.setLink(newTopic.getLink());
      ticketDTO.setTitle(newTopic.getTopicName());
      ticketDTO.setStartDate(newTopic.getCreatedDate().toString());
      convertToEntity(ticketDTO, topicEntity, environmentEntity);
      topicDAO.create(topicEntity);
      Map<String,String> data = new HashMap<>();
      data.put(CSConstants.USERID,user.getUserName());
      listenerService.broadcast(CSConstants.TICKET_CREATED,topicEntity,data);
    } else {
      // In case the types defined IssueType has evolved
      throw new UnsupportedOperationException("Method saveUser - argument ticketDTO.type is not recognized");
    }
  }

  private void updateForumTags(TicketDTO ticketDTO, Topic topic, String oldSeverity, String oldType) throws Exception{
    Tag tagSeverity,tagType;
    List<String> userIds = ForumServiceUtils.getUserPermission(new String[]{"*:"+ticketDTO.getSpaceGroupId()});
    if (userIds != null && !userIds.isEmpty()) {
      tagSeverity = forumService.getTag(Utils.TAG+ticketDTO.getSeverity().name());
      if(tagSeverity == null){
        tagSeverity = new Tag();
        tagSeverity.setUserTag(userIds.toArray(new String[0]));
        tagSeverity.setName(ticketDTO.getSeverity().name());
        tagSeverity.setId(Utils.TAG+ticketDTO.getSeverity().name());
      }
      tagType = forumService.getTag(Utils.TAG+ticketDTO.getType().name());
      if(tagType == null) {
        tagType = new Tag();
        tagType.setUserTag(userIds.toArray(new String[0]));
        tagType.setName(ticketDTO.getType().name());
        tagType.setId(Utils.TAG + ticketDTO.getType().name());
      }
      List<Tag> tags = new ArrayList<>();
      tags.add(tagSeverity);
      tags.add(tagType);
      boolean notSaved = false;
      do {
        // Save new Tag
        try {
          for (String userId : userIds) {
            if(oldType != null && !oldType.isEmpty()){
              forumService.unTag(Utils.TAG+oldType,userId,topic.getPath());
            }
            if(oldSeverity != null && !oldSeverity.isEmpty()){
              forumService.unTag(Utils.TAG+oldSeverity,userId,topic.getPath());
            }
            forumService.addTag(tags, userId, topic.getPath());
          }
          notSaved = false;
        } catch (ItemExistsException e) {
          notSaved = true;
        }
      } while (notSaved);
    } else {
      LOG.warn("Can't Save new Tag, no users found in the group {}",ticketDTO.getSpaceGroupId());
    }

    }

  private Status getSpaceProjectStatus(String spaceGroupId, String username) {
    Long spaceProjectId = null;
    if (spaceGroupId != null) {
      List<Project> projects = ProjectUtil.flattenTree(ProjectUtil.getProjectTree(spaceGroupId, projectService), projectService);
      for (Project p : projects) {
        if (p.canView(new Identity(username))) {
          spaceProjectId = p.getId();
        }
      }
    }
    if (spaceProjectId == null) {
      throw new IllegalStateException("Can't fin adequate tasks project for space: " + spaceGroupId);
    }
    Status status = statusService.getDefaultStatus(spaceProjectId);
    return status;
  }

  private void convertToEntity(TicketDTO ticketDTO,
                               TopicEntity topicEntity,
                               EnvironmentEntity environmentEntity) throws Exception{
    topicEntity.setId(ticketDTO.getId());
    topicEntity.setEnvironment(environmentEntity);
    SpaceEntity spaceEntity = spaceDAO.find(ticketDTO.getSpaceGroupId());
    topicEntity.setSpace(spaceEntity);
    topicEntity.setType(ticketDTO.getType());
    topicEntity.setSeverity(ticketDTO.getSeverity());
    topicEntity.setInfoType(ticketDTO.getInfoType());
    topicEntity.setLink(ticketDTO.getLink());
    topicEntity.setAssignee(ticketDTO.getAssignee());
    topicEntity.setStatus(ticketDTO.getStatus());
    topicEntity.setUpdateDate(convertToCalendar(ticketDTO.getUpdateDate()));
    topicEntity.setCreationDate(convertToCalendar(ticketDTO.getStartDate()));
    topicEntity.setTitle(ticketDTO.getTitle());
  }

  /**
   * Converts a Topic entity to a ticket DTO
   * @param topicEntity
   * @param space
   * @return a ticket DTO representing the topic entity
   */
  private TicketDTO convertToDTO(TopicEntity topicEntity, SpaceEntity space) {
    try {
      TicketDTO ticketDTO = new TicketDTO();
      ticketDTO.setId(topicEntity.getId());
      ticketDTO.setEnvironmentName(topicEntity.getEnvironment() == null ? null : topicEntity.getEnvironment().getName());
      ticketDTO.setSeverity(topicEntity.getSeverity());
      ticketDTO.setInfoType(topicEntity.getInfoType());
      ticketDTO.setLink(topicEntity.getLink());
      ticketDTO.setType(topicEntity.getType());
      ticketDTO.setAssignee(topicEntity.getAssignee());
      ticketDTO.setSpaceGroupId(space.getGroupId());
      if(topicEntity.getUpdateDate() != null) {
        String updateDate = topicEntity.getUpdateDate().getTime().toString();
        String formattedUpdateDate = convertDate(DEFAULT_DATE_FORMAT_USED_FOR_TOPICS, updateDate);
        ticketDTO.setUpdateDate(formattedUpdateDate);
      }
      if(topicEntity.getTitle() != null && !topicEntity.getTitle().isEmpty()){
        ticketDTO.setTitle(topicEntity.getTitle());
      }
      if (topicEntity.getCreationDate() != null) {
        String startDate = topicEntity.getCreationDate().getTime().toString();
        String ticketDate = convertDate(DEFAULT_DATE_FORMAT_USED_FOR_TOPICS, startDate);
        ticketDTO.setStartDate(ticketDate);
      }
      ticketDTO.setStatus(topicEntity.getStatus());

      switch (topicEntity.getType()) {
        case INFORMATION:
          ticketDTO.setFlow(space.getInformationFlow());
        case INCIDENT:
          ticketDTO.setFlow(space.getIncidentFlow());
          ticketDTO.setEnvironmentId(topicEntity.getEnvironment() == null ? null : topicEntity.getEnvironment().getId());
          break;
        case PRODUCT:
          long taskId = Long.parseLong(topicEntity.getId());
          Task task = null;
          try {
            task = taskService.getTask(taskId);
          } catch (EntityNotFoundException e) {
            LOG.warn("Task with id '{}' was not found", topicEntity.getId());
          }
          if (task == null) {
            break;
          }
          if(topicEntity.getCreationDate() != null){
            String ticketDateTask = DEFAULT_DATE_FORMAT_USED_FOR_TASKS.format(topicEntity.getCreationDate().getTime());
            ticketDTO.setStartDate(ticketDateTask);
          }
          ticketDTO.setStatus(task.getStatus() == null ? "inprogress" : task.getStatus().getName());
          break;
        default:
          break;
      }

      return ticketDTO;
    } catch (Exception e) {
    LOG.error("error converting ticket {} from space of group {}",topicEntity.getId(), space.getGroupId(), e);
  }
    return null;
  }

  private List<TicketDTO> convertToDTO(List<TopicEntity> entities){
    List<TicketDTO> tickets = new ArrayList<TicketDTO>();
    for (TopicEntity topicEntity : entities) {
      SpaceEntity space = topicEntity.getSpace();
      String groupId = space.getGroupId();
      TicketDTO ticket = convertToDTO(topicEntity, space);
      if(ticket != null) {
        tickets.add(ticket);
      }
    }
    return tickets;
  }

  private String convertDate(DateFormat dateFormat, String startDate) {
    Date date = null;
    try {
      date = dateFormat.parse(startDate);
    } catch (ParseException e) {
      LOG.error("Error when parsing date",e);
    }
    if (date != null) {
      return DATE_FORMAT_TO_CONVERT_USED_FOR_TICKETS.format(date);
    } else {
      return null;
    }
  }
  

  private Calendar convertToCalendar(String dateToFormat){
    Calendar cal = Calendar.getInstance();
    try {
      Date date = DATE_FORMAT_TO_CONVERT_USED_FOR_TICKETS.parse(dateToFormat);
      cal.setTime(date);
    } catch (Exception e) {
      LOG.debug("Error when converting {} to a date using formatter {} ", dateToFormat, DATE_FORMAT_DISPLAYED_IN_TICKETS_LIST);
    }
    return cal;
  }

  /**
   * Delete a ticket and the related task or forum topic
   * @param ticket The ticket to delete
   */
  public void deleteTicket(TicketDTO ticket) {
    TopicEntity entity = topicDAO.find(ticket.getId());
    if(IssueType.PRODUCT == entity.getType()) {
      try {
        taskService.removeTask(Long.parseLong(entity.getId()));
      } catch (EntityNotFoundException e) {
        LOG.error("Task {} was not found, ticket entry will be deleted!",entity.getId() != null ? entity.getId():"");
      }
    } else {
      try {
        Category spaceCategory = forumService.getCategoryIncludedSpace();
        String groupId = entity.getSpace().getGroupId();
        Forum spaceForum = ForumUtils.getSpaceForum(forumService, groupId);
        forumService.removeTopic(spaceCategory.getId(),spaceForum.getId(),entity.getId());
      } catch (Exception e) {
        LOG.error("Topic {} could not be removed or is not found, ticket entry will be deleted!",entity.getId() != null ? entity.getId():"");
      }
    }
    topicDAO.delete(entity);
  }

  List<TicketDTO> getTickets(Calendar fromDate, Calendar toDate) {
    List<TopicEntity> tickets = topicDAO.findUpdatedBetween(fromDate,toDate);
    return convertToDTO(tickets);
  }

  public Long getTicketsCount(SpaceEntity space, IssueType type) {
     return topicDAO.countTickets(space,type);
  }
}
