package com.eactive.testmaster.server.mapper;


import com.eactive.testmaster.common.exception.NotFoundException;
import com.eactive.testmaster.server.dto.ServerDTO;
import com.eactive.testmaster.server.dto.ServerOptionDTO;
import com.eactive.testmaster.server.entity.Server;
import com.eactive.testmaster.server.entity.ServerOption;
import com.eactive.testmaster.server.repository.ServerRepository;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Mapper(componentModel = "spring",
    unmappedTargetPolicy = ReportingPolicy.IGNORE)
@Component
public class ServerMapper {

    @Autowired
    ServerRepository serverRepository;

    public Server mapById(Long id) {
        if (id == null || id == 0) {
            return null;
        }
        return serverRepository.findById(id).orElseThrow(() -> new NotFoundException("Server[" + id + "] not found"));
    }

    public Long mapById(Server server) {
        if (server == null) {
            return null;
        }
        return server.getId();
    }

    public ServerDTO map(Server server) {
        if (server == null) {
            return null;
        }
        ServerDTO dto = new ServerDTO();

        dto.setId(server.getId());
        dto.setName(server.getName());
        dto.setHostname(server.getHostname());
        dto.setPort(server.getPort());
        dto.setScheme(server.getScheme());
        dto.setBasePath(server.getBasePath());
        dto.setEnabled(server.isEnabled());
        dto.setServerOptions(mapOptionsDTO(server.getServerOptions()));

        return dto;
    }


    public Server map(ServerDTO dto) {
        if (dto == null) {
            return null;
        }

        Server server = new Server();

        server.setId(dto.getId());
        server.setName(dto.getName());
        server.setHostname(dto.getHostname());
        server.setPort(dto.getPort());
        server.setScheme(dto.getScheme());
        server.setBasePath(dto.getBasePath());
        server.setEnabled(dto.isEnabled());
        server.setServerOptions(mapOptions(dto.getServerOptions()));

        return server;
    }
    public List<ServerOption> mapOptions(List<ServerOptionDTO> dtos) {
        if (dtos == null) {
            return new ArrayList<>();
        }
        return dtos.stream().map(this::map).filter(Objects::nonNull).collect(Collectors.toList());
    }

    public List<ServerOptionDTO> mapOptionsDTO(List<ServerOption> entities) {
        if (entities == null) {
            return new ArrayList<>();
        }
        return entities.stream().map(this::map).filter(Objects::nonNull).collect(Collectors.toList());
    }


    public ServerOption map(ServerOptionDTO dto){
        if (dto == null) {
            return null;
        }

        if (dto.getOptionKey() == null && dto.getOptionName() == null && dto.getDefaultValue() == null && dto.getOffset() == null && dto.getLength() == null) {
            return null;
        }

        ServerOption serverOption = new ServerOption();

        serverOption.setOptionId(dto.getOptionId());
        serverOption.setOptionKey(dto.getOptionKey());
        serverOption.setOptionName(dto.getOptionName());
        serverOption.setDefaultValue(dto.getDefaultValue());
        serverOption.setOffset(dto.getOffset());
        serverOption.setLength(dto.getLength());
        serverOption.setEnabled(dto.isEnabled());

        return serverOption;

    }

    public ServerOptionDTO map(ServerOption entity){
        if (entity == null) {
            return null;
        }

        ServerOptionDTO dto = new ServerOptionDTO();

        dto.setOptionId(entity.getOptionId());
        dto.setOptionKey(entity.getOptionKey());
        dto.setOptionName(entity.getOptionName());
        dto.setDefaultValue(entity.getDefaultValue());
        dto.setOffset(entity.getOffset());
        dto.setLength(entity.getLength());
        dto.setEnabled(entity.isEnabled());

        return dto;
    }


    public List<ServerDTO> map(List<Server> servers) {
        return servers.stream().map(this::map).collect(Collectors.toList());
    }
}
