/*
 * Copyright 2017 Philip Fritzsche <p-f@users.noreply.github.com>.
 *
 * 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 one.p_f.testing.msagimport.grouping.io.dot;

import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.gradoop.common.model.impl.pojo.Edge;
import org.gradoop.common.model.impl.pojo.Vertex;
import org.gradoop.common.model.impl.properties.Property;
import org.gradoop.flink.io.impl.dot.functions.DOTFileFormat;
import org.gradoop.flink.representation.transactional.GraphTransaction;

/**
 * Improve the {@link DOTFileFormat} to produce valid and nicer DOT output.
 *
 * @author p-f
 * @see one.p_f.testing.msagimport.grouping.io.dot.ImprovedDotDataSink
 */
public class ImprovedDotFileFormat extends DOTFileFormat {

    private static final char NL = '\n';

    private static final char ATTR_PREFIX = 'a';

    private static final String ATTR_SHAPE = "rect";

    private static final char NODE_PREFIX = 'v';

    public ImprovedDotFileFormat() {
        super(false);
    }

    @Override
    public String format(GraphTransaction transaction) {
        StringBuilder dot = new StringBuilder().append("digraph ")
                .append('g')
                .append(transaction.getGraphHead().getId())
                .append(" {\n");
        writeVertices(transaction, dot);
        writeEdges(transaction, dot);
        dot.append(NL).append('}');
        return dot.toString();
    }

    private static void writeEdges(GraphTransaction tr, StringBuilder sb) {
        for (Edge e : tr.getEdges()) {
            String from = String.format("%c%s", NODE_PREFIX,
                    e.getSourceId().toString());
            String to = String.format("%c%s", NODE_PREFIX,
                    e.getTargetId().toString());
            Stream<Property> propStream = e.getProperties() == null
                    ? Stream.of()
                    : StreamSupport
                            .stream(e.getProperties().spliterator(), false);
            String prop = propStream
                    .map(f -> f.getKey() + ": " + f.getValue())
                    .collect(Collectors.joining("\\n", "\"", "\""));
            sb.append(String.format("%s%s [label=%s,shape=\"%s\"];%c",
                    from, to, prop, ATTR_SHAPE, NL));
            sb.append(String.format("%s -> %s;%c", from, from + to, NL));
            sb.append(String.format("%s -> %s;%c", from + to, to, NL));
        }
    }

    private static void writeVertices(GraphTransaction tr, StringBuilder sb) {
        for (Vertex v : tr.getVertices()) {
            String id = v.getId().toString();
            // Write vertex.
            sb.append(String.format("%c%s [label=\"%s\", shape=\"ellipse\"];%c",
                    NODE_PREFIX, id, v.getLabel(), NL));
            Stream<Property> propStream = v.getProperties() == null
                    ? Stream.of()
                    : StreamSupport
                            .stream(v.getProperties().spliterator(), false);
            String prop = propStream
                    .map(f -> f.getKey() + ": " + f.getValue())
                    .collect(Collectors.joining("\\n", "\"", "\""));
            sb.append(String.format("%c%s_attr [label=%s,shape=\"%s\"];%c",
                    NODE_PREFIX, id, prop, ATTR_SHAPE, NL));
            sb.append(String.format("%c%s -> %c%s_attr;%c", NODE_PREFIX, id,
                    NODE_PREFIX, id, NL));
        }
    }
}

@@ -719,40 +719,8 @@
 rs;%0A
-import java.util.stream.Stream;%0A
 impo
@@ -856,66 +856,8 @@
 ex;%0A
-import org.gradoop.common.model.impl.properties.Property;%0A
 impo
@@ -2244,68 +2244,143 @@
     
-Stream%3CProperty%3E propStream = e.getProperties() == null%0A    
+if (e.getProperties() == null %7C%7C e.getProperties().isEmpty()) %7B%0A                sb.append(String.format(%22%25s -%3E %25s;%25c%22, from, to, NL));%0A
     
@@ -2387,37 +2387,33 @@
             
-? Stream.of()
+continue;
 %0A           
@@ -2401,32 +2401,38 @@
 ntinue;%0A        
+    %7D%0A
             : St
@@ -2419,33 +2419,45 @@
   %7D%0A            
-:
+String prop =
  StreamSupport%0A 
@@ -2451,32 +2451,24 @@
 reamSupport%0A
-        
             
@@ -2526,46 +2526,8 @@
 lse)
-;%0A            String prop = propStream
 %0A   
@@ -2630,33 +2630,33 @@
 tors.joining(%22%5C%5C
-n
+l
 %22, %22%5C%22%22, %22%5C%22%22));
@@ -2642,32 +2642,35 @@
 (%22%5C%5Cl%22, %22%5C%22%22, %22%5C
+%5Cl%5C
 %22%22));%0A          
@@ -2829,27 +2829,64 @@
 %25s -%3E %25s
-;%25c%22, from,
+ %5Barrowhead=none%5D;%25c%22, from,%0A                   
  from + 
@@ -3336,38 +3336,12 @@
     
-Stream%3CProperty%3E propStream = 
+if (
 v.ge
@@ -3361,16 +3361,19 @@
  == null
+) %7B
 %0A       
@@ -3385,47 +3385,57 @@
     
-    ? Stream.of()%0A                    :
+continue;%0A            %7D%0A            String prop =
  Str
@@ -3441,32 +3441,24 @@
 reamSupport%0A
-        
             
@@ -3516,46 +3516,8 @@
 lse)
-;%0A            String prop = propStream
 %0A   
@@ -3628,17 +3628,17 @@
 ning(%22%5C%5C
-n
+l
 %22, %22%5C%22%22,
@@ -3640,16 +3640,19 @@
 %22%5C%22%22, %22%5C
+%5Cl%5C
 %22%22));%0A  
@@ -3831,16 +3831,21 @@
 %25c%25s
+_attr
  -%3E %25c%25s
 _att
@@ -3840,21 +3840,36 @@
  -%3E %25c%25s
-_attr
+ %5Barrowhead=diamond%5D
 ;%25c%22, NO

Remove attribute nodes iff there are no attributes