# -*- coding: utf-8 -*-
#
#  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.

"""Simple command-line sample for Google Maps Engine.

This sample code demonstrates use of the Google Maps Engine API.  For more
information on the API, see developers.google.com/maps-engine/documentation/

These samples allow you to
1) List projects you have access to
2) List tables in a given project.
3) Upload a shapefile to create a Table asset.

Usage:
  $ python maps_engine.py [-p project_id] [-s shapefile]

If you do not enter a shapefile, it will upload the included "polygons".

You can also get help on all the command-line flags the program understands
by running:

  $ python maps_engine.py --help

To get detailed log output run:

  $ python maps_engine.py -p 123456 --logging_level=DEBUG
"""

__author__ = "jlivni@google.com (Josh Livni)"

import argparse
import json
import logging
import sys
import time

from apiclient import sample_tools
from apiclient.http import MediaFileUpload

logging.basicConfig(level=logging.INFO)

# Declare command-line flags.
argparser = argparse.ArgumentParser(add_help=False)
argparser.add_argument("-p", "--project_id", help="optional GME Project ID")
argparser.add_argument("-s", "--shapefile", help="Shapefile (without the .shp)")

SUCCESSFUL_STATUS = ["processed", "complete", "ready"]


class MapsEngineSampleException(Exception):
  """Catch this for failures specific to this sample code."""


def ListProjects(service):
  """List the projects available to the authorized account.

  Args:
    service: The service object built by the Google API Python client library.
  """
  projects = service.projects().list().execute()
  logging.info(json.dumps(projects, indent=2))


def ListTables(service, project_id):
  """List the tables in a given project.

  Args:
    service: The service object built by the Google API Python client library.
    project_id: string, id of the GME project.
  """

  tables = service.tables().list(projectId=project_id).execute()
  logging.info(json.dumps(tables, indent=2))


def UploadShapefile(service, project_id, shapefile_prefix):
  """Upload a shapefile to a given project, and display status when complete.

  Args:
    service: The service object built by the Google API Python client library.
    project_id: string, id of the GME project.
    shapefile_prefix: string, the shapefile without the .shp suffix.

  Returns:
    String id of the table asset.
  """
  # A shapefile is actually a bunch of files; GME requires these four suffixes.
  suffixes = ["shp", "dbf", "prj", "shx"]
  files = []
  for suffix in suffixes:
    files.append({
        "filename": "%s.%s" % (shapefile_prefix, suffix)
    })
  metadata = {
      "projectId": project_id,
      "name": shapefile_prefix,
      "description": "polygons that were uploaded by a script",
      "files": files,
      # You need the string value of a valid shared and published ACL
      # Check the "Access Lists" section of the Maps Engine UI for a list.
      "draftAccessList": "Map Editors",
      "tags": [shapefile_prefix, "auto_upload", "kittens"]
  }

  logging.info("Uploading metadata for %s", shapefile_prefix)
  response = service.tables().upload(body=metadata).execute()
  # We have now created an empty asset.
  table_id = response["id"]

  # And now upload each of the files individually, passing in the table id.
  for suffix in suffixes:
    shapefile = "%s.%s" % (shapefile_prefix, suffix)
    media_body = MediaFileUpload(shapefile, mimetype="application/octet-stream")
    logging.info("uploading %s", shapefile)

    response = service.tables().files().insert(
        id=table_id,
        filename=shapefile,
        media_body=media_body).execute()

  # With all files uploaded, check status of the asset to ensure it's processed.
  CheckAssetStatus(service, "tables", table_id)
  return table_id


def CheckAssetStatus(service, asset_type, asset_id):
  endpoint = getattr(service, asset_type)
  response = endpoint().get(id=asset_id).execute()
  status = response["processingStatus"]
  logging.info("Asset Status: %s", status)
  if status in SUCCESSFUL_STATUS:
    logging.info("asset successfully processed; the id is %s", asset_id)
  else:
    logging.info("Asset %s; will check again in 5 seconds", status)
    time.sleep(5)
    CheckAssetStatus(service, asset_type, asset_id)


def main(argv):
  # Authenticate and construct service.
  service, flags = sample_tools.init(
      argv, "mapsengine", "v1", __doc__, __file__, parents=[argparser],
      scope="https://www.googleapis.com/auth/mapsengine")

  if flags.project_id:
    # ListTables(service, flags.project_id)
    # The example polygons shapefile should be in this directory.
    filename = flags.shapefile or "polygons"
    table_id = UploadShapefile(service, flags.project_id, filename)
    logging.info("Sucessfully created table: %s", table_id)
  else:
    ListProjects(service)
  return


if __name__ == "__main__":
  main(sys.argv)
