package com.altamiracorp.lumify.web.routes.entity;

import com.altamiracorp.lumify.core.model.audit.AuditAction;
import com.altamiracorp.lumify.core.model.audit.AuditRepository;
import com.altamiracorp.lumify.core.model.detectedObjects.DetectedObjectModel;
import com.altamiracorp.lumify.core.model.detectedObjects.DetectedObjectRepository;
import com.altamiracorp.lumify.core.model.ontology.Concept;
import com.altamiracorp.lumify.core.model.ontology.LabelName;
import com.altamiracorp.lumify.core.model.ontology.OntologyRepository;
import com.altamiracorp.lumify.core.model.user.UserRepository;
import com.altamiracorp.lumify.core.security.VisibilityTranslator;
import com.altamiracorp.lumify.core.user.User;
import com.altamiracorp.lumify.core.util.GraphUtil;
import com.altamiracorp.lumify.web.BaseRequestHandler;
import com.altamiracorp.miniweb.HandlerChain;
import com.altamiracorp.securegraph.Authorizations;
import com.altamiracorp.securegraph.Graph;
import com.altamiracorp.securegraph.Vertex;
import com.altamiracorp.securegraph.Visibility;
import com.altamiracorp.securegraph.mutation.ElementMutation;
import com.google.inject.Inject;
import org.json.JSONObject;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static com.altamiracorp.lumify.core.model.ontology.OntologyLumifyProperties.CONCEPT_TYPE;
import static com.altamiracorp.lumify.core.model.properties.LumifyProperties.TITLE;

public class ResolveDetectedObject extends BaseRequestHandler {
    private final Graph graph;
    private final AuditRepository auditRepository;
    private final OntologyRepository ontologyRepository;
    private final UserRepository userRepository;
    private final DetectedObjectRepository detectedObjectRepository;
    private final VisibilityTranslator visibilityTranslator;

    @Inject
    public ResolveDetectedObject(
            final Graph graphRepository,
            final AuditRepository auditRepository,
            final OntologyRepository ontologyRepository,
            final UserRepository userRepository,
            final DetectedObjectRepository detectedObjectRepository,
            final VisibilityTranslator visibilityTranslator) {
        this.graph = graphRepository;
        this.auditRepository = auditRepository;
        this.ontologyRepository = ontologyRepository;
        this.userRepository = userRepository;
        this.detectedObjectRepository = detectedObjectRepository;
        this.visibilityTranslator = visibilityTranslator;
    }

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, HandlerChain chain) throws Exception {
        final String artifactId = getRequiredParameter(request, "artifactId");
        final String title = getRequiredParameter(request, "title");
        final String conceptId = getRequiredParameter(request, "conceptId");
        final String visibilitySource = getRequiredParameter(request, "visibilitySource");
        final String rowKey = getOptionalParameter(request, "rowKey");
        final String graphVertexId = getOptionalParameter(request, "graphVertexId");
        String x1 = getRequiredParameter(request, "x1"), x2 = getRequiredParameter(request, "x2"),
                y1 = getRequiredParameter(request, "y1"), y2 = getRequiredParameter(request, "y2");

        User user = getUser(request);
        Authorizations authorizations = userRepository.getAuthorizations(user);
        Visibility visibility = visibilityTranslator.toVisibility(visibilitySource);

        Concept concept = ontologyRepository.getConceptById(conceptId);
        Vertex artifactVertex = graph.getVertex(artifactId, authorizations);
        Vertex resolvedVertex;
        ElementMutation<Vertex> resolvedVertexMutation;
        DetectedObjectModel detectedObjectModel;
        Object id = graphVertexId != null && !graphVertexId.equals("") ? graphVertexId : graph.getIdGenerator().nextId();

        if (rowKey != null) {
            detectedObjectModel = detectedObjectRepository.findByRowKey(rowKey, user.getModelUserContext());
            detectedObjectModel.getMetadata().setResolvedId(id, visibility);
            detectedObjectRepository.save(detectedObjectModel);
        } else {
            detectedObjectModel = detectedObjectRepository.saveDetectedObject(artifactId, id, conceptId, Double.parseDouble(x1), Double.parseDouble(y1), Double.parseDouble(x2), Double.parseDouble(y2), true, null, visibility);
        }

        if (graphVertexId == null || graphVertexId.equals("")) {
            resolvedVertexMutation = graph.prepareVertex(id, visibility, authorizations);
            CONCEPT_TYPE.setProperty(resolvedVertexMutation, concept.getId(), visibility);
            TITLE.setProperty(resolvedVertexMutation, title, visibility);

            resolvedVertex = resolvedVertexMutation.save();
            auditRepository.auditVertexElementMutation(resolvedVertexMutation, resolvedVertex, "", user, visibility);

        } else {
            resolvedVertex = graph.getVertex(id, authorizations);
        }
        JSONObject result = detectedObjectModel.toJson();
        result.put("entityVertex", GraphUtil.toJson(resolvedVertex));

        graph.addEdge(artifactVertex, resolvedVertex, LabelName.RAW_CONTAINS_IMAGE_OF_ENTITY.toString(), visibility, authorizations);
        String labelDisplayName = ontologyRepository.getDisplayNameForLabel(LabelName.RAW_CONTAINS_IMAGE_OF_ENTITY.toString());
        // TODO: replace second "" when we implement commenting on ui
        auditRepository.auditRelationship(AuditAction.CREATE, artifactVertex, resolvedVertex, labelDisplayName, "", "", user, visibility);

        // TODO: index the new vertex

        graph.flush();

        respondWithJson(response, result);
    }
}

@@ -4146,32 +4146,388 @@
 d, visibility);%0A
+            detectedObjectModel.getMetadata().setX1(Double.parseDouble(x1), visibility);%0A            detectedObjectModel.getMetadata().setX2(Double.parseDouble(x2), visibility);%0A            detectedObjectModel.getMetadata().setY1(Double.parseDouble(y1), visibility);%0A            detectedObjectModel.getMetadata().setY2(Double.parseDouble(y2), visibility);%0A
             dete

save edited coordinates for detected objects