/**
 * (C) Copyright 2015 Chiral Behaviors, LLC. All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.chiralbehaviors.CoRE.workspace.dsl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.chiralbehaviors.CoRE.workspace.dsl.WorkspaceParser.ExistentialRuleformContext;
import com.chiralbehaviors.CoRE.workspace.dsl.WorkspaceParser.ImportedWorkspaceContext;
import com.chiralbehaviors.CoRE.workspace.dsl.WorkspaceParser.IntervalContext;
import com.chiralbehaviors.CoRE.workspace.dsl.WorkspaceParser.RelationshipPairContext;
import com.chiralbehaviors.CoRE.workspace.dsl.WorkspaceParser.SequencePairContext;
import com.chiralbehaviors.CoRE.workspace.dsl.WorkspaceParser.StatusCodeSequencingSetContext;
import com.chiralbehaviors.CoRE.workspace.dsl.WorkspaceParser.UnitContext;
import com.chiralbehaviors.CoRE.workspace.dsl.WorkspaceParser.WorkspaceContext;
import com.hellblazer.utils.Tuple;

/**
 * @author hhildebrand
 *
 */
public class WorkspacePresentation {
    public static class RelationshipPair {
        public final Tuple<String, String> inverse;

        public final String                inverseWsName;
        public final Tuple<String, String> primary;
        public final String                primaryWsName;

        public RelationshipPair(String primaryWsName,
                                Tuple<String, String> primary,
                                String inverseWsName,
                                Tuple<String, String> inverse) {
            this.primaryWsName = primaryWsName;
            this.primary = primary;
            this.inverseWsName = inverseWsName;
            this.inverse = inverse;
        }
    }

    private final WorkspaceContext context;

    public WorkspacePresentation(WorkspaceContext context) {
        this.context = context;
    }

    public Map<String, Tuple<String, String>> getAgencies() {
        if (context.agencies == null) {
            return Collections.emptyMap();
        }
        return getRuleforms(context.agencies.existentialRuleform());
    }

    public Map<String, Tuple<String, String>> getAttributes() {
        if (context.attributes == null) {
            return Collections.emptyMap();
        }
        return getRuleforms(context.attributes.existentialRuleform());
    }

    public List<Tuple<String, Tuple<String, String>>> getEdges() {
        List<Tuple<String, Tuple<String, String>>> edges = new ArrayList<>();
        return edges;
    }

    public List<Tuple<String, String>> getImports() {
        if (context.imports == null) {
            return Collections.emptyList();
        }
        List<Tuple<String, String>> imports = new ArrayList<>();
        for (ImportedWorkspaceContext wsp : context.imports.importedWorkspace()) {
            imports.add(new Tuple<String, String>(wsp.uri.getText(),
                                                  wsp.namespace.getText()));
        }
        return imports;
    }

    public List<IntervalContext> getIntervals() {
        if (context.intervals == null) {
            return Collections.emptyList();
        }

        return context.intervals.interval();
    }

    public Map<String, Tuple<String, String>> getLocations() {
        if (context.locations == null) {
            return Collections.emptyMap();
        }
        return getRuleforms(context.locations.existentialRuleform());
    }

    public Map<String, Tuple<String, String>> getProducts() {
        if (context.products == null) {
            return Collections.emptyMap();
        }
        return getRuleforms(context.products.existentialRuleform());
    }

    public List<RelationshipPair> getRelationships() {
        if (context.relationships == null) {
            return Collections.emptyList();
        }
        List<RelationshipPair> pairs = new ArrayList<>();
        for (RelationshipPairContext pair : context.relationships.relationshipPair()) {
            pairs.add(new RelationshipPair(
                                           pair.primary.getText(),
                                           new Tuple<String, String>(
                                                                     pair.primary.name.getText(),
                                                                     pair.primary.description.getText()),
                                           pair.inverse.getText(),
                                           new Tuple<String, String>(
                                                                     pair.inverse.name.getText(),
                                                                     pair.inverse.description.getText())));
        }
        return pairs;
    }

    public Map<String, Tuple<String, String>> getStatusCodes() {
        if (context.statusCodes == null) {
            return Collections.emptyMap();
        }
        return getRuleforms(context.statusCodes.existentialRuleform());
    }

    public Map<String, List<Tuple<String, String>>> getStatusCodeSequencings() {
        if (context.statusCodeSequencings == null) {
            return Collections.emptyMap();
        }

        Map<String, List<Tuple<String, String>>> sequencings = new HashMap<>();
        for (StatusCodeSequencingSetContext ctx : context.statusCodeSequencings.statusCodeSequencingSet()) {
            List<Tuple<String, String>> sequencePairs = new ArrayList<>();
            for (SequencePairContext pairCtx : ctx.sequencePair()) {
                sequencePairs.add(new Tuple<String, String>(
                                                            pairCtx.first.getText(),
                                                            pairCtx.second.getText()));
            }
            sequencings.put(ctx.service.getText(), sequencePairs);
        }

        return sequencings;
    }

    public List<UnitContext> getUnits() {
        if (context.units == null) {
            return Collections.emptyList();
        }

        return context.units.unit();
    }

    public Tuple<String, String> getWorkspaceDefinition() {
        return new Tuple<String, String>(
                                         context.definition.name.getText(),
                                         context.definition.description.getText());
    }

    private Map<String, Tuple<String, String>> getRuleforms(List<ExistentialRuleformContext> rfContext) {
        Map<String, Tuple<String, String>> ruleforms = new HashMap<>();
        for (ExistentialRuleformContext ruleform : rfContext) {
            ruleforms.put(ruleform.workspaceName.getText(),
                          new Tuple<String, String>(
                                                    ruleform.name.getText(),
                                                    ruleform.description == null ? null
                                                                                : ruleform.description.getText()));
        }
        return ruleforms;
    }
}

@@ -1590,693 +1590,8 @@
 on %7B
-%0A    public static class RelationshipPair %7B%0A        public final Tuple%3CString, String%3E inverse;%0A%0A        public final String                inverseWsName;%0A        public final Tuple%3CString, String%3E primary;%0A        public final String                primaryWsName;%0A%0A        public RelationshipPair(String primaryWsName,%0A                                Tuple%3CString, String%3E primary,%0A                                String inverseWsName,%0A                                Tuple%3CString, String%3E inverse) %7B%0A            this.primaryWsName = primaryWsName;%0A            this.primary = primary;%0A            this.inverseWsName = inverseWsName;%0A            this.inverse = inverse;%0A        %7D%0A    %7D
 %0A%0A  
@@ -3552,16 +3552,23 @@
 shipPair
+Context
 %3E getRel
@@ -3578,24 +3578,24 @@
 onships() %7B%0A
-
         if (
@@ -3693,904 +3693,55 @@
     
-List%3CRelationshipPair%3E pairs = new ArrayList%3C%3E();%0A        for (RelationshipPairContext pair : context.relationships.relationshipPair()) %7B%0A            pairs.add(new RelationshipPair(%0A                                           pair.primary.getText(),%0A                                           new Tuple%3CString, String%3E(%0A                                                                     pair.primary.name.getText(),%0A                                                                     pair.primary.description.getText()),%0A                                           pair.inverse.getText(),%0A                                           new Tuple%3CString, String%3E(%0A                                                                     pair.inverse.name.getText(),%0A                                                                     pair.inverse.description.getText())));%0A        %7D%0A        return pairs
+return context.relationships.relationshipPair()
 ;%0A  

Use relationship pair context parse node.