#!/usr/bin/env python
# Copyright (c) 2013 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.

import argparse
import os
import re
import sys

import build_version
from build_paths import SDK_SRC_DIR, SCRIPT_DIR, OUT_DIR

# Add SDK make tools scripts to the python path.
sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))

import getos

VALID_PLATFORMS = ['linux', 'mac', 'win']
PLATFORM_PREFIX_RE = re.compile(r'^\[([^\]]*)\](.*)$')

class ParseException(Exception):
  def __init__(self, filename, line, message):
    Exception.__init__(self)
    self.filename = filename
    self.line = line
    self.message = message

  def __str__(self):
    return '%s:%d: %s' % (self.filename, self.line, self.message)


def SplitPattern(pattern):
  match = PLATFORM_PREFIX_RE.match(pattern)
  if not match:
    return pattern, []

  # platform-specific line
  platforms = match.group(1).split(',')

  # If this platform is included, strip the [...] part.
  pattern = match.group(2)
  return pattern, platforms


class VerifyException(Exception):
  pass

class Rules(object):
  def __init__(self, filename, platform=None, contents=None):
    self.glob_prefixes = []
    self.exact_filenames = set()
    self.filename = filename
    self.platform = platform or getos.GetPlatform()
    self.exe_ext = '.exe' if self.platform == 'win' else ''

    if self.platform not in VALID_PLATFORMS:
      raise ParseException(self.filename, 1,
                           'Unknown platform %s' % self.platform)

    if not contents:
      with open(filename) as f:
        contents = f.read()

    for line_no, rule in enumerate(contents.split('\n')):
      rule = rule.strip()
      if rule:
        self.ParsePattern(line_no + 1, rule)

  def ParsePattern(self, line_no, pattern):
    pattern, platforms = SplitPattern(pattern)
    if platforms:
      unknown_platforms = set(platforms) - set(VALID_PLATFORMS)
      if unknown_platforms:
        msg = 'Unknown platform(s) %s.' % (
            ', '.join('"%s"' % platform for platform in unknown_platforms))
        raise ParseException(self.filename, line_no, msg)
      if self.platform not in platforms:
        return

    pattern = pattern.replace('${PLATFORM}', self.platform)
    pattern = pattern.replace('${EXE_EXT}', self.exe_ext)

    if '*' in pattern:
      # glob pattern
      # We only support * at the end.
      if pattern.find('*') != len(pattern) - 1:
        msg = '* is only allowed at the end of the line.'
        raise ParseException(self.filename, line_no, msg)

      # Remove the *
      pattern = pattern[:-1]
      self.glob_prefixes.append(pattern)
      # Sort by longest prefix first; otherwise the rules:
      #
      # foo/*
      # foo/bar/*
      #
      # Won't work properly. A file "foo/bar/baz" will match the first rule,
      # not the second.
      self.glob_prefixes.sort(cmp=lambda x, y: cmp(len(y), len(x)))
    else:
      self.exact_filenames.add(pattern)

  def VerifyDirectoryList(self, directory_list):
    exact_filenames_used = set()
    glob_prefixes_used = set()
    expected_globs = set()
    expected_filenames = set()
    unexpected_filenames = set()

    for filename in directory_list:
      if os.path.sep != '/':
        filename = filename.replace(os.path.sep, '/')
      if filename in self.exact_filenames:
        exact_filenames_used.add(filename)
        continue

      # glob pattern
      found_prefix = False
      for prefix in self.glob_prefixes:
        if filename.startswith(prefix):
          glob_prefixes_used.add(prefix)
          found_prefix = True
          break

      if not found_prefix:
        unexpected_filenames.add(filename)

    if len(exact_filenames_used) != len(self.exact_filenames):
      # We looped through the directory list, so if the lengths are unequal, it
      # must be that we expected something that isn't there.
      expected_filenames = self.exact_filenames - exact_filenames_used

    if len(glob_prefixes_used) != self.glob_prefixes:
      expected_globs = set(self.glob_prefixes) - glob_prefixes_used

    if expected_filenames or unexpected_filenames or expected_globs:
      msg = ''
      if unexpected_filenames:
        msg += '>>> Unexpected filenames: <<<\n%s\n' % (
            '\n'.join(sorted(unexpected_filenames)))
      if expected_filenames:
        msg += '>>> Expected filenames: <<<\n%s\n' % (
            '\n'.join(sorted(expected_filenames)))
      if expected_globs:
        msg += '>>> Expected 1+ files in these directories: <<< \n%s\n' % (
            '\n'.join(sorted(expected_globs)))
      raise VerifyException(msg)


def GetDirectoryList(directory_path):
  result = []
  for root, _, files in os.walk(directory_path):
    rel_root = os.path.relpath(root, directory_path)
    if rel_root == '.':
      rel_root = ''
    for base_name in files:
      result.append(os.path.join(rel_root, base_name))
  return result


def Verify(rule_path, directory_path, platform=None):
  rules = Rules(rule_path, platform=platform)
  directory_list = GetDirectoryList(directory_path)
  rules.VerifyDirectoryList(directory_list)


def SortFile(rule_path):
  with open(rule_path) as infile:
    lines = infile.readlines()

  def compare(line1, line2):
    line1 = SplitPattern(line1)[0].lower()
    line2 = SplitPattern(line2)[0].lower()
    return cmp(line1, line2)

  lines.sort(compare)
  with open(rule_path, 'w') as output:
    for line in lines:
      output.write(line)


def main(args):
  parser = argparse.ArgumentParser(description=__doc__)
  parser.add_argument('-p', '--platform',
      help='Test with this platform, instead of the system\'s platform')
  parser.add_argument('-s', '--sort', action='store_true',
      help='Sort the file list in place, rather than verifying the contents.')
  parser.add_argument('rule_file', nargs='?',
                      default=os.path.join(SCRIPT_DIR, 'sdk_files.list'))
  parser.add_argument('directory_path', nargs='?')
  options = parser.parse_args(args)

  if options.sort:
    SortFile(options.rule_file)
    return 0

  if not options.directory_path:
    version = build_version.ChromeMajorVersion()
    options.directory_path = os.path.join(OUT_DIR, 'pepper_%s' % version)

  if options.platform:
    if options.platform not in VALID_PLATFORMS:
      parser.error('Unknown platform: %s' % options.platform)
    platform = options.platform
  else:
    platform = getos.GetPlatform()

  try:
    return Verify(options.rule_file, options.directory_path, platform)
  except ParseException, e:
    sys.stderr.write('Error parsing rules:\n%s\n' % e)
    return 1
  except VerifyException, e:
    sys.stderr.write('Error verifying file list:\n%s\n' % e)
    return 1
  return 0


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
