// Copyright 2018 The Bazel Authors. 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 build.buildfarm.worker;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

// would be great to be able to inherit from ImmutableMap...
public class OutputDirectory extends HashMap<String, OutputDirectory> {
  private OutputDirectory() {
  }

  public static OutputDirectory parse(Iterable<String> outputFiles, Iterable<String> outputDirs) {
    return parseDirectories(Iterables.mergeSorted(
        ImmutableList.<Iterable<String>>of(
            Iterables.transform(
                outputFiles,
                (file) -> file.contains("/") ? file.substring(0, file.lastIndexOf('/') + 1) : ""),
            outputDirs),
        (a, b) -> a.compareTo(b)));
  }

  private static OutputDirectory parseDirectories(Iterable<String> outputDirs) {
    OutputDirectory outputDirectory = new OutputDirectory();
    Stack<OutputDirectory> stack = new Stack<>();

    OutputDirectory currentOutputDirectory = outputDirectory;
    String prefix = "";
    for (String outputDir : outputDirs) {
      while (!outputDir.startsWith(prefix)) {
        currentOutputDirectory = stack.pop();
        int upPathSeparatorIndex = prefix.lastIndexOf('/', prefix.length() - 2);
        prefix = prefix.substring(0, upPathSeparatorIndex + 1);
      }
      String prefixedFile = outputDir.substring(prefix.length());
      while (prefixedFile.length() > 0) {
        int separatorIndex = prefixedFile.indexOf('/');
        if (separatorIndex == 0) {
          throw new IllegalArgumentException("double separator in output directory");
        }

        String directoryName = separatorIndex == -1 ? prefixedFile : prefixedFile.substring(0, separatorIndex);
        prefix += directoryName + '/';
        prefixedFile = separatorIndex == -1 ? "" : prefixedFile.substring(separatorIndex + 1);
        stack.push(currentOutputDirectory);
        OutputDirectory nextOutputDirectory = new OutputDirectory();
        currentOutputDirectory.put(directoryName, nextOutputDirectory);
        currentOutputDirectory = nextOutputDirectory;
      }
    }

    return outputDirectory;
  }

  public void stamp(Path root) throws IOException {
    if (isEmpty()) {
      Files.createDirectories(root);
    } else {
      for (Map.Entry<String, OutputDirectory> entry : entrySet()) {
        entry.getValue().stamp(root.resolve(entry.getKey()));
      }
    }
  }
}

@@ -834,23 +834,104 @@
 va.util.
-HashMap
+ArrayList;%0Aimport java.util.Collections;%0Aimport java.util.HashMap;%0Aimport java.util.List
 ;%0Aimport
@@ -1753,16 +1753,201 @@
 k%3C%3E();%0A%0A
+    List%3CString%3E sortedOutputDirs = new ArrayList%3C%3E();%0A    Iterables.addAll(sortedOutputDirs, Iterables.transform(outputDirs, (d) -%3E d + %22/%22));%0A    Collections.sort(sortedOutputDirs);%0A%0A
     Outp
@@ -2052,17 +2052,23 @@
 utDir : 
-o
+sortedO
 utputDir
@@ -2380,16 +2380,40 @@
 length()
+, outputDir.length() - 1
 );%0A     

Transform outputDirs to have trailing slashes