package org.gcube.application.geoportal.common.model.document;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.vdurmont.semver4j.Semver;
import lombok.*;
import org.bson.Document;
import org.gcube.application.geoportal.common.model.document.accounting.PublicationInfo;
import org.gcube.application.geoportal.common.model.document.identification.IdentificationReference;
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
import org.gcube.application.geoportal.common.model.document.relationships.Relationship;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class Project {

    public static final String ID="_id";
    public static final String VERSION="_version";
    public static final String INFO="_info";
    public static final String PROFILE_ID="_profileID";
    public static final String PROFILE_VERSION="_profileVersion";
    public static final String LIFECYCLE_INFORMATION="_lifecycleInformation";
    public static final String RELATIONSHIPS="_relationships";
    public static final String IDENTIFICATION_REFERENCES="_identificationReferences";
    public static final String THE_DOCUMENT="_theDocument";
    public static final String LOCK="_lock";

    // CORE METADATA

    @JsonProperty(ID)
    private String id;
    @JsonProperty(VERSION)
    private Semver version;

    // Publication Info
    @JsonProperty(INFO)
    private PublicationInfo info;

    // UseCaseDescriptor reference
    @JsonProperty(PROFILE_ID)
    private String profileID;
    @JsonProperty(PROFILE_VERSION)
    private Semver profileVersion;

    @JsonProperty(LIFECYCLE_INFORMATION)
    private LifecycleInformation lifecycleInformation;

    @JsonProperty(RELATIONSHIPS)
    private List<Relationship> relationships;

    @JsonProperty(IDENTIFICATION_REFERENCES)
    private List<IdentificationReference> identificationReferences;

    @JsonProperty(THE_DOCUMENT)
    private Document theDocument;

    @JsonProperty(LOCK)
    private Lock lock;


    /**
     * Similar to equals but without checking following fields
     *
     *              lock
     * @param o
     * @return
     */
    public boolean isEquivalent(Object o) {
        if (this == o) return true;
        if (!(o instanceof Project)) return false;
        Project project = (Project) o;
        return Objects.equals(getId(), project.getId()) && Objects.equals(getVersion(), project.getVersion()) && Objects.equals(getInfo(), project.getInfo()) && Objects.equals(getProfileID(), project.getProfileID()) && Objects.equals(getProfileVersion(), project.getProfileVersion()) && Objects.equals(getLifecycleInformation(), project.getLifecycleInformation()) && Objects.equals(getIdentificationReferences(), project.getIdentificationReferences()) && Objects.equals(getRelationships(), project.getRelationships()) && Objects.equals(getTheDocument(), project.getTheDocument());
    }


    @JsonIgnore
    public List<IdentificationReference> getIdentificationReferenceByType(String type){
        if(identificationReferences==null) return Collections.emptyList();
        else return identificationReferences.stream()
                .filter(item -> item.getType().equals(type)).collect(Collectors.toList());
    };

    @JsonIgnore
    public List<Relationship> getRelationshipsByName(String relation){
        if(relationships==null)return Collections.emptyList();
        else return relationships.stream().filter(relationship -> relationship.
                getRelationshipName().equals(relation)).collect(Collectors.toList());
    };


    @JsonIgnore
    public Project addRelation(Relationship rel){
        if(relationships==null) relationships = new ArrayList<>();
        relationships.add(rel);
        return this;
    }
}
