#!/usr/bin/env python3
# Copyright 2016 The Fontbakery Authors
# Copyright 2017 The Google Font Tools Authors
#
# 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.
#
"""
Generate a test html snippet for a family hosted on fonts.google.com

This script works well for quickly producing test cases using jsbin.

$ fontbakery family-html-snippet "Exo" "Hello World"
>>> ...
<html>
  <head>
    <link href="https://fonts.googleapis.com/css?family=Exo"/rel="stylesheet">
    <style>
      .g{font-family: 'Exo'; font-weight:400;}
      .h{font-family: 'Exo'; font-weight:400; font-style: italic;}
      .m{font-family: 'Exo'; font-weight:700;}
      .n{font-family: 'Exo'; font-weight:700; font-style: italic;}
    </style>
  </head>
  <body>
    <p class='g'>Hello World</p>
    <p class='h'>Hello World</p>
    <p class='m'>Hello World</p>
    <p class='n'>Hello World</p>
  </body>
</html>
"""
from __future__ import print_function
import json
import requests
import sys
from argparse import (ArgumentParser,
                      RawTextHelpFormatter)

GF_API = "https://www.googleapis.com/webfonts/v1/webfonts?key={}"

GF_API_WEIGHT_TO_CSS_WEIGHT = {
  "100": "100",
  "100italic": "100i",
  "200": "200",
  "200italic": "200i",
  "300": "300",
  "300italic": "300i",
  "regular": "400",
  "italic": "400i",
  "500": "500",
  "500italic": "500i",
  "600": "600",
  "600italic": "600i",
  "700": "700",
  "700italic": "700i",
  "800": "800",
  "800italic": "800i",
  "900": "900",
  "900italic": "900i"
}

API_TO_CSS_STYLE_NAME = {
  "100": "a",
  "100i": "b",
  "200": "c",
  "200i": "d",
  "300": "e",
  "300i": "f",
  "400": "g",
  "400i": "h",
  "500": "i",
  "500i": "j",
  "600": "k",
  "600i": "l",
  "700": "m",
  "700i": "n",
  "800": "o",
  "800i": "p",
  "900": "q",
  "900i": "r",
}


def get_gf_family(family, api_key):
  """Get data of the given family hosted on Google Fonts"""
  request = requests.get(GF_API.format(api_key))

  try:
    response = json.loads(request.text)
    if "error" in response:
      if response["error"]["errors"][0]["reason"] == "keyInvalid":
        sys.exit(("The Google Fonts API key '{}'"
                  " was rejected as being invalid !").format(api_key))
      else:
        sys.exit(("There were errors in the"
                  " Google Fonts API request:"
                  " {}").format(response["error"]))
    else:
      gf_families = response
  except (ValueError, KeyError):
    sys.exit("Unable to load and parse data from Google Web Fonts API.")

  for item in gf_families['items']:
    if family == item['family']:
        return item
  return False


def get_family_styles(gf_family):
  """Get all the styles of a family"""
  styles = []
  if gf_family:
      for var in gf_family['variants']:
        styles.append((GF_API_WEIGHT_TO_CSS_WEIGHT[var]))
  return styles


def get_family_subsets(family_subsets, gf_family):
  """Get all the valid subsets from the given family"""
  valid_subsets = []
  if family_subsets:
    for subset in family_subsets:
      if subset in gf_family['subsets']:
        valid_subsets.append(subset)
  return valid_subsets


def gen_head_webfonts(family, styles, subsets=None):
  """Gen the html snippet to load fonts"""
  server = '"https://fonts.googleapis.com/css?family='
  if subsets:
    return '<link href=%s%s:%s&amp;subset=%s" /rel="stylesheet">' % (
      server, family.replace(' ', '+'), ','.join(styles), ','.join(subsets)
    )
  return '<link href=%s%s:%s" /rel="stylesheet">' % (
    server, family.replace(' ', '+'), ','.join(styles)
  )


def gen_css_styles(family, styles):
  css = []
  for style in styles:
    if style.endswith('i'):
      css.append((".%s{font-family: '%s'; "
                  "font-weight:%s; "
                  "font-style: italic;}" % (
                    API_TO_CSS_STYLE_NAME[style],
                    family,
                    style[:-1])
                  ))
    else:
      css.append((".%s{font-family: '%s'; "
                  "font-weight:%s;}" % (
                    API_TO_CSS_STYLE_NAME[style],
                    family,
                    style)
                  ))
  return css


def gen_body_text(styles, sample_text):
  html = []
  for style in styles:
    html.append("<p class='%s'>%s</p>" % (
      API_TO_CSS_STYLE_NAME[style],
      sample_text)
    )
  return html


def main(args=None):
  parser = ArgumentParser(description=__doc__,
                          formatter_class=RawTextHelpFormatter)
  parser.add_argument('key',
                      help='Key from Google Fonts Developer API')
  parser.add_argument('family',
                      help='family name on fonts.google.com')
  parser.add_argument('sample_text',
                      help='sample text used for each font')
  parser.add_argument('--subsets', nargs='+',
                      help='family subset(s) seperated by a space')
  args = parser.parse_args(args)

  gf_family = get_gf_family(args.family, args.key)
  family_styles = get_family_styles(gf_family)
  family_subsets = get_family_subsets(args.subsets, gf_family)

  if family_subsets:
    head_fonts = gen_head_webfonts(args.family, family_styles, family_subsets)
  else:
    head_fonts = gen_head_webfonts(args.family, family_styles)

  css_styles = gen_css_styles(args.family, family_styles)
  body_text = gen_body_text(family_styles, args.sample_text)

  html = """
<html>
  <head>
    %s
    <style>
      %s
    </style>
  </head>
  <body>
    %s
  </body>
</html>""" % (
    head_fonts,
    '\n      '.join(css_styles),
    '\n    '.join(body_text)
  )
  print(html)


if __name__ == '__main__':
  main()
