#!/usr/bin/env python
#
# Copyright 2014 Google Inc. All rights reserved.
#
# 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.

"""Base code for copying and unpacking font drops from vendors.

See grab_mt_download.py and grab_adobe_download.py"""

__author__ = "dougfelt@google.com (Doug Felt)"

import argparse
import os
import os.path
import re
import shutil


def grab_files(dst, files, src_vendor, name_date_re, extract_fn):
  """Get date from each filename in files, create a folder for it, under
  dst/drops, then extract the files to it."""

  # The zip indicates that the corresponding drop is good and built from it. But
  # we might have messed up along the way, so:
  # - if we have a drop and a zip, assume it's already handled
  # - if we have a drop but no zip, assume the drop needs to be rebuilt from the zip
  # - if we have a zip and no drop
  #   - if we have new zip, complain
  #   - else rebuild the drop from the old zip
  # - else build the drop, and if successful, save the zip

  for f in files:
    if not os.path.exists(f):
      print('file \'%s\' does not exist, skipping' % f)
      continue

    filename = os.path.basename(f)
    result = name_date_re.match(filename)
    if not result:
      print('could not parse %s, skipping' % f)
      continue

    name = result.group(1)
    date = '_'.join([d for d in result.group(2,3,4)])
    drop_dir = os.path.join(dst, 'drops', name + '_' + date)

    zip_dir = os.path.join(dst, 'zips')
    zip_filename = os.path.join(zip_dir, filename)
    if os.path.exists(drop_dir):
      if os.path.exists(zip_filename):
        print('already have a %s drop and zip for %s' % (src_vendor, filename))
        continue
      else:
        # clean up, assume needs rebuild
        shutil.rmtree(drop_dir)
    else:
      if os.path.exists(zip_filename):
        if os.path.realpath(f) != os.path.realpath(zip_filename):
          print('already have a zip file named %s for %s' % (zip_filename, f))
          continue

    os.mkdir(drop_dir)
    extract_fn(drop_dir, f)

    if not os.path.exists(zip_filename):
      print('writing %s to %s' % (f, zip_filename))
      shutil.copy2(f, zip_filename)


def matching_files_in_dir(src, namere):
  """Iterate over files in src with names matching namere, returning the list."""
  filelist = []
  for f in os.listdir(src):
    path = os.path.join(src, f)
    if not os.path.isfile(path):
      continue
    if not re.search(namere, f):
      continue
    filelist.append(path)
  if not filelist:
    print("no files in %s matched '%s'" % (src, namere))
  return filelist


def invoke_main(src_vendor, name_date_re, extract_fn, default_params = {}):
  """Grab the files.

  src_vendor is a string, currently either Adobe or Monotype.
  name_date_re is a regex, it should extract name, year, month, and day fields from the filename
  extract_fn is a fn to to extract a file, it takes two args, a dest dir and the zip file name.

  default_params are default values for argparse.  They can be:
  - default_srcdir
  - default_dstdir
  - default_regex

  The default regex and the name_date_re are superficially similar, but different in
  purpose.  The default_regex is used to select files under the src directory. The
  name_date_re is used to extract the date from the file name.  Both apply to the
  file name, but the default_regex can be anything, while name_date_re needs to select
  four groups, where the 2nd, 3rd, and 4th are the year, month, and day (yes this is
  brittle, but all of this is).

  The dest directory must exist and should have 'zips' and 'drops' subdirs."""

  if not src_vendor:
    print('must define src_vendor')
    return
  if not name_date_re:
    print('must define name_date_re')
    return
  if not extract_fn:
    print('must define extract_fn')
    return

  default_srcdir = default_params.get('default_srcdir')
  default_dstdir = default_params.get('default_dstdir')
  default_regex = default_params.get('default_regex')

  parser = argparse.ArgumentParser(description='Copy and extract drop from %s.' %
                                   src_vendor)
  parser.add_argument('-dd', '--dstdir', help='destination directory (default %s)' %
                      default_dstdir, default=default_dstdir, metavar='dst')
  parser.add_argument('-sd', '--srcdir', help='source directory (default %s)' %
                      default_srcdir, default=default_srcdir, metavar='src')
  parser.add_argument('--name', help='file name regex to match (default \'%s\')' %
                      default_regex, default=default_regex, metavar='re')
  parser.add_argument('--srcs', help='source files (if defined, use instead of srcdir+name)',
                      nargs="*", metavar='zip')
  args = parser.parse_args()

  if not os.path.exists(args.dstdir):
    print('%s does not exists or is not a directory' % args.dstdir)
    return

  if not args.srcs:
    if not os.path.isdir(args.srcdir):
      print('%s does not exist or is not a directory' % args.srcdir)
      return
    filelist = matching_files_in_dir(args.srcdir, args.name)
  else:
    filelist = args.srcs

  grab_files(args.dstdir, filelist, src_vendor, name_date_re, extract_fn)
