# 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.

import base64
import os
import re


class Image(object):

  def __init__(self, resource):
    self.resource = resource
    self.aliases = []

  @property
  def relative_path(self):
    return self.resource.relative_path

  @property
  def absolute_path(self):
    return self.resource.absolute_path

  @property
  def contents(self):
    return self.resource.contents


class ParsedStyleSheet(object):
  def __init__(self, loader, containing_dirname, contents):
    self.loader = loader
    self.contents = contents
    self._images = None
    self._Load(containing_dirname)

  @property
  def images(self):
    return self._images

  def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
    for i in self.images:
      dependent_filenames.append(i.resource.absolute_path)

  @property
  def contents_with_inlined_images(self):
    images_by_url = {}
    for i in self.images:
      for a in i.aliases:
        images_by_url[a] = i

    def InlineUrl(m):
      url = m.group('url')
      image = images_by_url[url]

      ext = os.path.splitext(image.absolute_path)[1]
      data = base64.standard_b64encode(image.contents)

      return "url(data:image/%s;base64,%s)" % (ext[1:], data)

    # I'm assuming we only have url()'s associated with images
    return re.sub('url\((?P<quote>"|\'|)(?P<url>[^"\'()]*)(?P=quote)\)',
                  InlineUrl, self.contents)

  def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
    for i in self.images:
      dependent_filenames.append(i.resource.absolute_path)

  def _Load(self, containing_dirname):
    if self.contents.find('@import') != -1:
      raise Exception('@imports are not supported')

    matches = re.findall(
        'url\((?:["|\']?)([^"\'()]*)(?:["|\']?)\)',
        self.contents)

    def resolve_url(url):
      if os.path.isabs(url):
        # FIXME: module is used here, but tvcm.module is never imported.
        # However, tvcm.module cannot be imported since tvcm.module may import
        # style_sheet, leading to an import loop.
        raise module.DepsException('URL references must be relative')
      # URLS are relative to this module's directory
      abs_path = os.path.abspath(os.path.join(containing_dirname, url))
      image = self.loader.LoadImage(abs_path)
      image.aliases.append(url)
      return image

    self._images = [resolve_url(x) for x in matches]


class StyleSheet(object):
  """Represents a stylesheet resource referenced by a module via the
  base.requireStylesheet(xxx) directive."""
  def __init__(self, loader, name, resource):
    self.loader = loader
    self.name = name
    self.resource = resource
    self._parsed_style_sheet = None

  @property
  def filename(self):
    return self.resource.absolute_path

  @property
  def contents(self):
    return self.resource.contents

  def __repr__(self):
    return "StyleSheet(%s)" % self.name

  @property
  def images(self):
    self._InitParsedStyleSheetIfNeeded()
    return self._parsed_style_sheet.images

  def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
    self._InitParsedStyleSheetIfNeeded()

    dependent_filenames.append(self.resource.absolute_path)
    self._parsed_style_sheet.AppendDirectlyDependentFilenamesTo(
        dependent_filenames)

  @property
  def contents_with_inlined_images(self):
    self._InitParsedStyleSheetIfNeeded()
    return self._parsed_style_sheet.contents_with_inlined_images

  def load(self):
    self._InitParsedStyleSheetIfNeeded()

  def _InitParsedStyleSheetIfNeeded(self):
    if self._parsed_style_sheet:
      return
    module_dirname = os.path.dirname(self.resource.absolute_path)
    self._parsed_style_sheet = ParsedStyleSheet(
        self.loader, module_dirname, self.contents)
