package eu.eudat.models.data.dmp;

import eu.eudat.data.entities.*;
import eu.eudat.models.DataModel;
import eu.eudat.models.data.dataset.Dataset;
import eu.eudat.models.data.funder.FunderDMPEditorModel;
import eu.eudat.models.data.grant.GrantDMPEditorModel;
import eu.eudat.models.data.project.ProjectDMPEditorModel;
import eu.eudat.models.data.userinfo.UserInfo;
import eu.eudat.models.data.userinfo.UserListingModel;
import net.minidev.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by ikalyvas on 2/5/2018.
 */
public class DataManagementPlanNewVersionModel implements DataModel<DMP, DataManagementPlanNewVersionModel> {
    private static final Logger logger = LoggerFactory.getLogger(DataManagementPlanNewVersionModel.class);

    private UUID id;
    private String label;
    private UUID groupId;
    private int version;
    private int status;
    private String description;
    private List<AssociatedProfile> profiles;
    private eu.eudat.models.data.grant.GrantDMPEditorModel grant;
    private List<Organisation> organisations;
    private List<Researcher> researchers;
    private List<UserListingModel> associatedUsers;
    private eu.eudat.models.data.userinfo.UserInfo creator;
    private Date created;
    private List<Dataset> datasets;
    private ProjectDMPEditorModel project;
    private FunderDMPEditorModel funder;
    private Map<String, Object> extraProperties;

    public UUID getId() {
        return id;
    }
    public void setId(UUID id) {
        this.id = id;
    }

    public String getLabel() {
        return label;
    }
    public void setLabel(String label) {
        this.label = label;
    }

    public UUID getGroupId() {
        return groupId;
    }
    public void setGroupId(UUID groupId) {
        this.groupId = groupId;
    }

    public int getVersion() {
        return version;
    }
    public void setVersion(int version) {
        this.version = version;
    }

    public int getStatus() {
        return status;
    }
    public void setStatus(int status) {
        this.status = status;
    }

    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }

    public List<AssociatedProfile> getProfiles() {
        return profiles;
    }
    public void setProfiles(List<AssociatedProfile> profiles) {
        this.profiles = profiles;
    }

    public GrantDMPEditorModel getGrant() {
        return grant;
    }
    public void setGrant(GrantDMPEditorModel grant) {
        this.grant = grant;
    }

    public List<Organisation> getOrganisations() {
        return organisations;
    }
    public void setOrganisations(List<Organisation> organisations) {
        this.organisations = organisations;
    }

    public List<Researcher> getResearchers() {
        return researchers;
    }
    public void setResearchers(List<Researcher> researchers) {
        this.researchers = researchers;
    }

    public List<UserListingModel> getAssociatedUsers() {
        return associatedUsers;
    }
    public void setAssociatedUsers(List<UserListingModel> associatedUsers) {
        this.associatedUsers = associatedUsers;
    }

    public UserInfo getCreator() {
        return creator;
    }
    public void setCreator(UserInfo creator) {
        this.creator = creator;
    }

    public Date getCreated() {
        return created;
    }
    public void setCreated(Date created) {
        this.created = created;
    }

    public List<Dataset> getDatasets() {
        return datasets;
    }
    public void setDatasets(List<Dataset> datasets) {
        this.datasets = datasets;
    }

    public ProjectDMPEditorModel getProject() {
        return project;
    }
    public void setProject(ProjectDMPEditorModel project) {
        this.project = project;
    }

    public FunderDMPEditorModel getFunder() {
        return funder;
    }
    public void setFunder(FunderDMPEditorModel funder) {
        this.funder = funder;
    }

    public Map<String, Object> getExtraProperties() {
        return extraProperties;
    }

    public void setExtraProperties(Map<String, Object> extraProperties) {
        this.extraProperties = extraProperties;
    }

    @Override
    public DataManagementPlanNewVersionModel fromDataModel(DMP entity) {
        return null;
    }

    @Override
    public DMP toDataModel() throws Exception {
        DMP entity = new DMP();
        entity.setId(this.id);
       // entity.setUsers(new HashSet<>(new ArrayList<>(this.associatedUsers)));
        entity.setDescription(this.description);
        entity.setStatus((short) this.status);
        entity.setGroupId(this.groupId == null ? UUID.randomUUID() : this.groupId);
        entity.setCreated(new Date());
        entity.setLabel(this.label);
        entity.setModified(new Date());
        List<eu.eudat.data.entities.Dataset> datasets = new LinkedList<>();
        if (this.datasets != null) {
            for (Dataset dataset : this.datasets) {
                eu.eudat.data.entities.Dataset entityDataset = new eu.eudat.data.entities.Dataset();
                entityDataset.setId(dataset.getId());
                datasets.add(entityDataset);
            }
            entity.setDataset(new HashSet<>(datasets));
        }
        if (this.organisations != null && !this.organisations.isEmpty())
            entity.setOrganisations(new HashSet<>(this.organisations.stream().map(item -> item.toDataModel()).collect(Collectors.toList())));
        if (this.researchers != null && !this.researchers.isEmpty())
            entity.setResearchers(new HashSet<>(this.researchers.stream().map(item -> item.toDataModel()).collect(Collectors.toList())));
        /*if (this.grant != null) {
            entity.setGrant(this.grant.toDataModel());
        }*/

        if (this.grant != null) {
            if (this.grant.getExistGrant() != null && this.grant.getLabel() == null && this.grant.getDescription() == null)
                entity.setGrant(this.grant.getExistGrant().toDataModel());
            else {
                eu.eudat.data.entities.Grant grant = new eu.eudat.data.entities.Grant();
                grant.setId(UUID.randomUUID());
                grant.setAbbreviation("");
                grant.setLabel(this.grant.getLabel());
                grant.setType(eu.eudat.data.entities.Grant.GrantType.INTERNAL.getValue());
                grant.setReference("dmp:" + (this.grant.getReference() != null ? this.grant.getReference() : grant.getId()));
                grant.setUri("");
                grant.setDefinition("");
                grant.setCreated(new Date());
                grant.setStatus(Grant.Status.ACTIVE.getValue());
                grant.setModified(new Date());
                grant.setDescription(this.grant.getDescription());

                entity.setGrant(grant);
            }
        }

        if (this.funder == null) {
            // dataManagementPlanEntity.getGrant().setFunder(null);
            throw new Exception("Funder is a mandatory entity");
        } else if (this.funder.getExistFunder() == null && this.funder.getLabel() == null) {
            // dataManagementPlanEntity.getGrant().setFunder(null);
            throw new Exception("Funder is a mandatory entity");
        } else {
            if (this.funder.getLabel() != null) {
                Funder funder = new Funder();
                funder.setId(UUID.randomUUID());
                funder.setLabel(this.funder.getLabel());
                funder.setType(Funder.FunderType.INTERNAL.getValue());
                funder.setReference("dmp:" + (this.funder.getReference() != null ? this.funder.getReference() : funder.getId()));
                funder.setDefinition("");
                funder.setCreated(new Date());
                funder.setStatus(Funder.Status.ACTIVE.getValue());
                funder.setModified(new Date());

                entity.getGrant().setFunder(funder);
            } else if (this.funder.getExistFunder() != null && this.funder.getLabel() == null) {
                entity.getGrant().setFunder(this.funder.getExistFunder().toDataModel());
                entity.getGrant().getFunder().setType(Funder.FunderType.EXTERNAL.getValue());
            }
        }

        if (this.project != null) {
            if (this.project.getExistProject() != null && this.project.getLabel() == null && this.project.getDescription() == null)
                entity.setProject(this.project.getExistProject().toDataModel());
            else {
                Project project = new Project();
                project.setId(UUID.randomUUID());
                project.setAbbreviation("");
                project.setLabel(this.project.getLabel());
                project.setType(Project.ProjectType.INTERNAL.getValue());
                project.setReference("dmp:" + (this.project.getReference() != null ? this.project.getReference() : project.getId()));
                project.setUri("");
                project.setDefinition("");
                project.setCreated(new Date());
                project.setStatus(Project.Status.ACTIVE.getValue());
                project.setModified(new Date());
                project.setDescription(this.project.getDescription());

                entity.setProject(project);
            }
        }

        entity.setExtraProperties(this.extraProperties != null ? JSONObject.toJSONString(this.extraProperties) : null);
        if (this.profiles != null)
            entity.setAssociatedDmps(this.profiles.stream().map(x -> x.toData()).collect(Collectors.toSet()));
        return entity;
    }

    @Override
    public String getHint() {
        return null;
    }
}
