"""Build steps to run Kythe commands on eureka internal."""

import os

from helpers import git_utils
from slave.step import shell_step

KYTHE_RUN_EXTRACTOR_BINARY = \
  "chromecast/internal/third_party/kythe/tools/runextractor"
KYTHE_CXX_EXTRACTOR_BINARY = \
  "chromecast/internal/third_party/kythe/extractors/cxx_extractor"
KYTHE_KZIP_BINARY = "chromecast/internal/third_party/kythe/tools/kzip"
EUREKA_INTERNAL_CORUPUS = "eureka-internal.googlesource.com/codesearch"
VNAMES_JSON_FILE_LOCATION = \
  "cq/scripts/resources/kythe_step/vnames.json"


class GenerateKzipStep(shell_step.ShellStep):

  def __init__(self, cwd, tests_root, chromium_root, out_dir, compdb_file,
               min_expected_kzip_bytes, *args, **kwargs):
    super().__init__(name="kythe_gen", cwd=cwd, *args, **kwargs)

    self._tests_root = tests_root
    self._chromium_root = chromium_root
    self._compdb_file = compdb_file
    self._min_kzip_size = min_expected_kzip_bytes

    self._runextractor_binary = os.path.join(self._chromium_root,
                                             KYTHE_RUN_EXTRACTOR_BINARY)
    self._cxx_extractor_binary = os.path.join(self._chromium_root,
                                              KYTHE_CXX_EXTRACTOR_BINARY)
    self._kzip_binary = os.path.join(self._chromium_root, KYTHE_KZIP_BINARY)
    self._kythe_output_directory = os.path.join(out_dir, "kythe-output")
    head_sha = git_utils.get_head_sha(self, directory=self._chromium_root)
    if head_sha is None:
      raise ValueError("Head SHA could not be determined for {}".format(
          self._chromium_root))
    self._merged_kzip_file = os.path.join(out_dir, head_sha + ".kzip")
    self._initialize_env()

  def get_kythe_output_file(self):
    return self._merged_kzip_file

  def _initialize_env(self):
    os.environ["KYTHE_ROOT_DIRECTORY"] = os.path.abspath(self._chromium_root)
    os.environ["KYTHE_CORPUS"] = EUREKA_INTERNAL_CORUPUS
    os.environ["KYTHE_OUTPUT_DIRECTORY"] = self._kythe_output_directory
    os.environ["KYTHE_VNAMES"] = os.path.join(self._tests_root,
                                              VNAMES_JSON_FILE_LOCATION)

  def get_commands(self):
    cmd_prep_output = ["mkdir", "-p", self._kythe_output_directory]
    cmd_gen_kzips = [
        self._runextractor_binary, "compdb", "-extractor",
        self._cxx_extractor_binary, "-path", self._compdb_file
    ]
    cmd_merge_kzips = [
        self._kzip_binary, "merge", "--output", self._merged_kzip_file,
        "--recursive", self._kythe_output_directory
    ]
    cmd_validate_kzip = ["du", "-b", self._merged_kzip_file]
    return [
        self.ShellCommand(cmd_prep_output, validator=self._validator),
        self.ShellCommand(cmd_gen_kzips, validator=self._validator),
        self.ShellCommand(cmd_merge_kzips, validator=self._validator),
        self.ShellCommand(
            cmd_validate_kzip, validator=self._validate_merged_kzip)
    ]

  def _validate_merged_kzip(self, returncode, stdout, stderr):
    if returncode != 0:
      return False

    byte_size = stdout.split()[0]
    return byte_size.isdigit() and int(byte_size) > self._min_kzip_size
