/*
 * Copyright 2017 flow.ci
 *
 * 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.flow.platform.api.service;

import com.flow.platform.api.domain.Flow;
import com.flow.platform.api.domain.Node;
import com.flow.platform.api.domain.Step;
import com.flow.platform.domain.Jsonable;
import com.google.common.io.Files;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.Yaml;


/**
 * @author lhl
 */
@Service(value = "yamlService")
public class YamlServiceImpl implements YamlService {

    @Autowired
    private NodeServiceImpl nodeService;

    @Override
    public Node createNode(File path) {
        try {
            String yamlString = Files.toString(path, Charset.forName("UTF-8"));
            Yaml yaml = new Yaml();
            Map result = (Map) yaml.load(yamlString);
            return createNode(result);
        } catch (Throwable ignore) {
            return null;
        }
    }

    @Override
    public Node createNode(String yamlString) {
        Yaml yaml = new Yaml();
        Map result = (Map) yaml.load(yamlString);
        return createNode(result);
    }

    private Node createNode(Map result) {
        if (result.get("flow") != null) {
            String rawJson = Jsonable.GSON_CONFIG.toJson(result.get("flow"));
            Flow[] flows = Jsonable.GSON_CONFIG.fromJson(rawJson, Flow[].class);


            for (int i = 0; i < flows.length; i++) {
                flows[i].setPath("/" + flows[i].getName());
                if (i > 0) {
                    flows[i].setPrev(flows[i - 1]);
                    flows[i - 1].setNext(flows[i]);
                }
                if (flows[i].getChildren() != null) {
                    String stepJson = Jsonable.GSON_CONFIG.toJson(flows[i].getChildren());
                    flows[i].setChildren(new ArrayList<>());
                    Node node = recursion(stepJson, flows[i]);
                    return nodeService.create(node);
                }
            }
        }
        return null;
    }

    private Node recursion(String nodes, Node node) {
        Step[] steps = Jsonable.GSON_CONFIG.fromJson(nodes, Step[].class);
        for (int j = 0; j < steps.length; j++) {
            node.getChildren().add(steps[j]);
            steps[j].setParent(node);
            steps[j].setPath(node.getPath() + "/" + steps[j].getName());
            if (j > 0) {
                steps[j].setPrev(steps[j - 1]);
                steps[j - 1].setNext(steps[j]);
            }

            if (steps[j].getChildren() != null) {
                String stepJson1 = Jsonable.GSON_CONFIG.toJson(steps[j].getChildren());
                steps[j].setChildren(new ArrayList<>());
                recursion(stepJson1, steps[j]);
            }
        }
        return node;
    }
}

@@ -711,50 +711,8 @@
 de;%0A
-import com.flow.platform.api.domain.Step;%0A
 impo
@@ -803,98 +803,12 @@
 .io.
-BufferedReader;%0Aimport java.io.File;%0Aimport java.io.FileReader;%0Aimport java.io.IOException
+File
 ;%0Aim
@@ -855,21 +855,16 @@
 va.util.
-Array
 List;%0Aim
@@ -1980,16 +1980,59 @@
 lass);%0A%0A
+            // build flow path and relation
 %0A       
@@ -2308,345 +2308,80 @@
     
-if (flows%5Bi%5D.getChildren() != null) %7B%0A                    String stepJson = Jsonable.GSON_CONFIG.toJson(flows%5Bi%5D.getChildren());%0A                    flows%5Bi%5D.setChildren(new ArrayList%3C%3E());%0A                    Node node = recursion(stepJson, flows%5Bi%5D);%0A                    return nodeService.create(node);%0A                %7D%0A            %7D
+buildNodeRelation(flows%5Bi%5D);%0A            %7D%0A%0A            return flows%5B0%5D;
 %0A   
@@ -2379,32 +2379,33 @@
 s%5B0%5D;%0A        %7D%0A
+%0A
         return n
@@ -2432,122 +2432,108 @@
 ate 
-Node recursion(String nodes, Node node) %7B%0A        Step%5B%5D steps = Jsonable.GSON_CONFIG.fromJson(nodes, Step%5B%5D.class
+%3CT extends Node%3E void buildNodeRelation(Node%3CT%3E root) %7B%0A        List%3CT%3E children = root.getChildren(
 );%0A 
@@ -2552,34 +2552,37 @@
 int 
-j
+i
  = 0; 
-j %3C steps.length; j
+i %3C children.size(); i
 ++) 
@@ -2599,140 +2599,117 @@
     
-node.getChildren().add(steps%5Bj%5D);%0A            steps%5Bj%5D.setParent(node);%0A            steps%5Bj%5D.setPath(node.getPath() + %22/%22 + steps%5Bj%5D
+T childNode = children.get(i);%0A            childNode.setPath(String.format(%22%25s/%25s%22, root.getPath(), childNode
 .get
@@ -2707,32 +2707,33 @@
 dNode.getName())
+)
 ;%0A            if
@@ -2734,66 +2734,32 @@
     
-if (j %3E 0) %7B%0A                steps%5Bj%5D
+childNode
 .setP
+a
 re
-v(steps%5Bj - 1%5D
+nt(root
 );%0A 
@@ -2773,43 +2773,20 @@
     
-    steps%5Bj - 1%5D.setNext(steps%5Bj%5D);
+if (i %3E 0) %7B
 %0A   
@@ -2798,298 +2798,173 @@
     
-%7D%0A%0A
     
-        if (steps%5Bj%5D.getChildren() != null) %7B%0A                String stepJson1 = Jsonable.GSON_CONFIG.toJson(steps%5Bj%5D.getChildren());%0A                steps%5Bj%5D.setChildren(new ArrayList%3C%3E());%0A                recursion(stepJson1, steps%5Bj%5D);%0A            %7D%0A        %7D%0A        return node;
+childNode.setPrev(children.get(i - 1));%0A                children.get(i - 1).setNext(childNode);%0A            %7D%0A            buildNodeRelation(childNode);%0A        %7D
 %0A   

refactor on build node relationship