#!/usr/bin/env python
#
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Renders one or more template files using the Jinja template engine."""

import codecs
import optparse
import os
import sys

from util import build_utils

sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
from pylib.constants import host_paths

# Import jinja2 from third_party/jinja2
sys.path.append(os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party'))
import jinja2  # pylint: disable=F0401


class RecordingFileSystemLoader(jinja2.FileSystemLoader):
  '''A FileSystemLoader that stores a list of loaded templates.'''
  def __init__(self, searchpath):
    jinja2.FileSystemLoader.__init__(self, searchpath)
    self.loaded_templates = set()

  def get_source(self, environment, template):
    contents, filename, uptodate = jinja2.FileSystemLoader.get_source(
        self, environment, template)
    self.loaded_templates.add(os.path.relpath(filename))
    return contents, filename, uptodate

  def get_loaded_templates(self):
    return list(self.loaded_templates)


def ProcessFile(env, input_filename, loader_base_dir, output_filename,
                variables):
  input_rel_path = os.path.relpath(input_filename, loader_base_dir)
  template = env.get_template(input_rel_path)
  output = template.render(variables)
  with codecs.open(output_filename, 'w', 'utf-8') as output_file:
    output_file.write(output)


def ProcessFiles(env, input_filenames, loader_base_dir, inputs_base_dir,
                 outputs_zip, variables):
  with build_utils.TempDir() as temp_dir:
    for input_filename in input_filenames:
      relpath = os.path.relpath(os.path.abspath(input_filename),
                                os.path.abspath(inputs_base_dir))
      if relpath.startswith(os.pardir):
        raise Exception('input file %s is not contained in inputs base dir %s'
                        % (input_filename, inputs_base_dir))

      output_filename = os.path.join(temp_dir, relpath)
      parent_dir = os.path.dirname(output_filename)
      build_utils.MakeDirectory(parent_dir)
      ProcessFile(env, input_filename, loader_base_dir, output_filename,
                  variables)

    build_utils.ZipDir(outputs_zip, temp_dir)


def main():
  parser = optparse.OptionParser()
  build_utils.AddDepfileOption(parser)
  parser.add_option('--inputs', help='The template files to process.')
  parser.add_option('--output', help='The output file to generate. Valid '
                    'only if there is a single input.')
  parser.add_option('--outputs-zip', help='A zip file containing the processed '
                    'templates. Required if there are multiple inputs.')
  parser.add_option('--inputs-base-dir', help='A common ancestor directory of '
                    'the inputs. Each output\'s path in the output zip will '
                    'match the relative path from INPUTS_BASE_DIR to the '
                    'input. Required if --output-zip is given.')
  parser.add_option('--loader-base-dir', help='Base path used by the template '
                    'loader. Must be a common ancestor directory of '
                    'the inputs. Defaults to DIR_SOURCE_ROOT.',
                    default=host_paths.DIR_SOURCE_ROOT)
  parser.add_option('--variables', help='Variables to be made available in the '
                    'template processing environment, as a GYP list (e.g. '
                    '--variables "channel=beta mstone=39")', default='')
  options, args = parser.parse_args()

  build_utils.CheckOptions(options, parser, required=['inputs'])
  inputs = build_utils.ParseGypList(options.inputs)

  if (options.output is None) == (options.outputs_zip is None):
    parser.error('Exactly one of --output and --output-zip must be given')
  if options.output and len(inputs) != 1:
    parser.error('--output cannot be used with multiple inputs')
  if options.outputs_zip and not options.inputs_base_dir:
    parser.error('--inputs-base-dir must be given when --output-zip is used')
  if args:
    parser.error('No positional arguments should be given.')

  variables = {}
  for v in build_utils.ParseGypList(options.variables):
    if '=' not in v:
      parser.error('--variables argument must contain "=": ' + v)
    name, _, value = v.partition('=')
    variables[name] = value

  loader = RecordingFileSystemLoader(options.loader_base_dir)
  env = jinja2.Environment(loader=loader, undefined=jinja2.StrictUndefined,
                           line_comment_prefix='##')
  if options.output:
    ProcessFile(env, inputs[0], options.loader_base_dir, options.output,
                variables)
  else:
    ProcessFiles(env, inputs, options.loader_base_dir, options.inputs_base_dir,
                 options.outputs_zip, variables)

  if options.depfile:
    deps = loader.get_loaded_templates() + build_utils.GetPythonDependencies()
    build_utils.WriteDepfile(options.depfile, deps)


if __name__ == '__main__':
  main()
