/*
 *
 *  * 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 java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.exoplatform.container.PortalContainer;
import org.exoplatform.cs.dto.TicketDTO;
import org.exoplatform.cs.entity.TopicEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.exoplatform.cs.dao.EnvironmentDAO;
import org.exoplatform.cs.dao.SpaceDAO;
import org.exoplatform.cs.dao.TopicDAO;
import org.exoplatform.cs.dao.TypeDAO;
import org.exoplatform.cs.dto.EnvironmentDTO;
import org.exoplatform.cs.dto.TypeDTO;
import org.exoplatform.cs.entity.EnvironmentEntity;
import org.exoplatform.cs.entity.SpaceEntity;
import org.exoplatform.cs.entity.TypeEntity;

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

  public EnvironmentService(EnvironmentDAO environmentDAO, SpaceDAO spaceDAO, TopicDAO topicDAO, TypeDAO typeDAO) {
    super(environmentDAO, spaceDAO, topicDAO, typeDAO);
  }

  public EnvironmentDTO getEnvironment(Long id) throws Exception {
    return convert(environmentDAO.find(id));
  }

  public EnvironmentDTO saveEnvironment(EnvironmentDTO environmentDTO) throws Exception {
    if (environmentDTO == null) {
      throw new IllegalStateException("Method save - Parameter 'environmentDTO' is null");
    }
    if (!environmentDTO.verifySaveConditions()) {
      throw new IllegalStateException("Method save - Parameter 'environmentDTO' is not coherent " + environmentDTO);
    }
    SpaceEntity spaceEntity = spaceDAO.find(environmentDTO.getSpaceGroupId());
    if (spaceEntity == null) {
      throw new IllegalStateException("Method save - Parameter 'environmentDTO.spaceGroupId' = '"
          + environmentDTO.getSpaceGroupId() + "' was not found in DB");
    }
    EnvironmentEntity environmentEntity = null;
    environmentDTO.setUpdateDate(Calendar.getInstance());
    if (environmentDTO.getId() == null) {
      environmentEntity = environmentDAO.create(convert(environmentDTO, spaceEntity, false));
    } else {
      environmentEntity = environmentDAO.update(convert(environmentDTO, spaceEntity, false));
    }
    if (environmentEntity.isDefaultEnvironment()) {
      // Ensure that only one environment is default
      String groupId = environmentDTO.getSpaceGroupId();
      List<EnvironmentEntity> environmentEntities = environmentDAO.getEnvironmentsBySpace(groupId);
      for (EnvironmentEntity otherEnvironmentEntity : environmentEntities) {
        if (otherEnvironmentEntity.getId() != environmentEntity.getId() && otherEnvironmentEntity.isDefaultEnvironment()) {
          otherEnvironmentEntity.setDefaultEnvironment(false);
          if (otherEnvironmentEntity.getId() == environmentEntity.getId()) {
            continue;
          }
          environmentDAO.update(otherEnvironmentEntity);
        }
      }
    }
    return convert(environmentEntity);
  }

  public void remove(EnvironmentDTO entity) {
    if (entity == null || entity.getId() == null) {
      throw new IllegalStateException("Parameter 'entity' = + " + entity + " or 'entity.id' is null");
    }
    entity.setSpaceGroupId(null);
    TicketService ticketService = PortalContainer.getInstance().getComponentInstanceOfType(TicketService.class);
    List<TopicEntity> tickets = ticketService.getTicketsEntityByEnvironment(entity.getId());
    for(TopicEntity ticket : tickets){
      ticket.setEnvironment(null);
       topicDAO.update(ticket);
    }
    environmentDAO.delete(convert(entity, null, true));
  }

  public List<EnvironmentDTO> getSpaceEnvironments(String spaceGroupId) throws Exception{
    List<EnvironmentDTO> dtos = new ArrayList<EnvironmentDTO>();
    List<EnvironmentEntity> environments = environmentDAO.getEnvironmentsBySpace(spaceGroupId);
    if (environments != null) {
      for (EnvironmentEntity environmentEntity : environments) {
        dtos.add(convert(environmentEntity));
      }
    }
    return dtos;
  }

  public List<EnvironmentDTO> getAllEnvironments() throws Exception{
    List<EnvironmentDTO> dtos = new ArrayList<EnvironmentDTO>();
    List<EnvironmentEntity> environments = environmentDAO.getAllEnvironments();
    if (environments != null) {
      for (EnvironmentEntity environmentEntity : environments) {
        dtos.add(convert(environmentEntity));
      }
    }
    return dtos;
  }
  public EnvironmentDTO getSpaceDefaultEnvironment(String spaceGroupId) throws Exception{
    EnvironmentEntity environment = environmentDAO.getDefaultEnvironmentBySpace(spaceGroupId);
    if (environment == null) {
      List<EnvironmentEntity> environments = environmentDAO.getEnvironmentsBySpace(spaceGroupId);
      if (environments != null) {
        environment = environments.get(0);
      }
    }
    return environment == null ? null : convert(environment);
  }

  public List<TypeDTO> getTypeObjects(String type) {
    Class<? extends TypeEntity> typeEntity = TypeDTO.getTypeFromString(type);
    List<? extends TypeEntity> entities = typeDAO.getTypeObjects(typeEntity);
    List<TypeDTO> typeDTOs = new ArrayList<TypeDTO>();
    for (TypeEntity entity : entities) {
      try {
        typeDTOs.add(TypeDTO.getDTOFromEntity(entity));
      } catch (Exception e) {
        LOG.error("Error occured while getting types : " + type, e);
      }
    }
    return typeDTOs;
  }

  public TypeDTO getTypeObject(String name, String type) {
    Class<? extends TypeEntity> typeEntityClass = TypeDTO.getTypeFromString(type);
    TypeEntity typeEntity = typeDAO.getTypeByName(name);
    if (typeEntityClass.isInstance(typeEntity)) {
      return TypeDTO.getDTOFromEntity(typeEntity);
    } else {
      return null;
    }
  }

  public TypeDTO saveType(TypeDTO typeDTO) throws Exception {
    TypeEntity typeEntity = TypeDTO.getEntityFromDTO(typeDTO);
    if (typeDTO.getId() < 1) {
      typeEntity.setId(null);
      typeEntity = typeDAO.create(typeEntity);
    } else {
      typeDAO.update(typeEntity);
    }
    return TypeDTO.getDTOFromEntity(typeEntity);
  }

  public void removeType(TypeDTO typeDTO) throws Exception {
    TypeEntity typeEntity = TypeDTO.getEntityFromDTO(typeDTO);
    if (typeDTO.getId() > 0) {
      typeDAO.delete(typeEntity);
    }
  }
}
