/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.flink.table.explain;

import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.DeserializationFeature;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.PropertyNamingStrategy;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * Utility for converting an execution plan from JSON to a human-readable string.
 */
public class PlanJsonParser {

	public static String getSqlExecutionPlan(String t, Boolean extended) throws Exception {
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

		// not every node is same, ignore the unknown field
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

		PlanTree tree = objectMapper.readValue(t, PlanTree.class);
		LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		int tabCount = 0;

		for (int index = 0; index < tree.getNodes().size(); index++) {
			Node tempNode = tree.getNodes().get(index);

			// input with operation such as join or union is coordinate, keep the same indent
			if ((tempNode.getPact().equals("Data Source")) && (map.containsKey(tempNode.getPact()))) {
				tabCount = map.get(tempNode.getPact());
			}
			else {
				map.put(tempNode.getPact(), tabCount);
			}

			printTab(tabCount, pw);
			pw.print("Stage " + tempNode.getId() + " : " + tempNode.getPact() + "\n");

			printTab(tabCount + 1, pw);
			String content = tempNode.getContents();

			// drop the hashcode of object instance
			int dele = tempNode.getContents().indexOf("@");
			if (dele > -1) {
				content = tempNode.getContents().substring(0, dele);
			}

			// replace with certain content if node is dataSource to pass
			// unit tests, because java and scala use different api to
			// get input element
			if (tempNode.getPact().equals("Data Source")) {
				content = "collect elements with CollectionInputFormat";
			}
			pw.print("content : " + content + "\n");

			List<Predecessors> predecessors = tempNode.getPredecessors();
			if (predecessors != null) {
				printTab(tabCount + 1, pw);
				pw.print("ship_strategy : " + predecessors.get(0).getShipStrategy() + "\n");

				String mode = predecessors.get(0).getExchangeMode();
				if (mode != null) {
					printTab(tabCount + 1, pw);
					pw.print("exchange_mode : " + mode + "\n");
				}
			}

			if (tempNode.getDriverStrategy() != null) {
				printTab(tabCount + 1, pw);
				pw.print("driver_strategy : " + tempNode.getDriverStrategy() + "\n");
			}

			if (tempNode.getGlobalProperties() != null) {
				printTab(tabCount + 1, pw);
				pw.print(tempNode.getGlobalProperties().get(0).getName() + " : "
					+ tempNode.getGlobalProperties().get(0).getValue() + "\n");
			}

			if (extended) {
				List<GlobalProperties> globalProperties = tempNode.getGlobalProperties();
				for (int i = 1; i < globalProperties.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(globalProperties.get(i).getName() + " : "
					+ globalProperties.get(i).getValue() + "\n");
				}

				List<LocalProperty> localProperties = tempNode.getLocalProperties();
				for (int i = 0; i < localProperties.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(localProperties.get(i).getName() + " : "
					+ localProperties.get(i).getValue() + "\n");
				}

				List<Estimates> estimates = tempNode.getEstimates();
				for (int i = 0; i < estimates.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(estimates.get(i).getName() + " : "
					+ estimates.get(i).getValue() + "\n");
				}

				List<Costs> costs = tempNode.getCosts();
				for (int i = 0; i < costs.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(costs.get(i).getName() + " : "
					+ costs.get(i).getValue() + "\n");
				}

				List<CompilerHints> compilerHints = tempNode.getCompilerHints();
				for (int i = 0; i < compilerHints.size(); i++) {
					printTab(tabCount + 1, pw);
					pw.print(compilerHints.get(i).getName() + " : "
					+ compilerHints.get(i).getValue() + "\n");
				}
			}
			tabCount++;
			pw.print("\n");
		}
		pw.close();
		return sw.toString();
	}

	private static void printTab(int tabCount, PrintWriter pw) {
		for (int i = 0; i < tabCount; i++) {
			pw.print("\t");
		}
	}
}

class PlanTree {
	private List<Node> nodes;

	public List<Node> getNodes() {
		return nodes;
	}
}
