#!/usr/bin/env python

"""Cosmid CLI

Usage:
  cosmid clone [<resource_id>...] [--save --dl-only --dry --collapse]
  cosmid update [<resource_id>...]
  cosmid init
  cosmid list
  cosmid search <query>
  cosmid (-h | --help)
  cosmid --version

Commands:
  clone               Download a new resource(s) locally
  update              Update local resources to the latest version
  list                List *all* available resources
  search              Search among the available resources
  init                Walk through setting up a basic project config file

Arguments:
  <resource_id>       List of resource IDs to clone or update
  <query>             Search term for matching against available resources

Options:
  -h --help           Show this screen
  -v --version        Show version
  -s --save           Add the successfully cloned resources to 'cosmid.yaml'
  -d --dry            Run in dry-mode keeping status quo
  -do --dl-only       Skip post download processing (unzip, concat etc.)
  -c --collapse       Save resources to a central directory
"""
from __future__ import print_function

import sys
from docopt import docopt
from path import path

import cosmid
from cosmid.core import Registry
from termcolor import colored


def main(args):
  # -------------------------------------------------------
  #  Search among the available resources
  # -------------------------------------------------------
  if args["search"]:
    # Search the registry using the query
    options = hub.search(args["<query>"])

    # Just to make sure we print something (feedback)
    print("\nSearch results:\n")

    # Print each of the matches (top 5) to the console as updates
    for option in options:
      hub.messenger.send("note", option[0])

  elif args["list"]:

    # Explaination
    print("\nAvailable resources (key - description):\n")

    # Get a list of all resources
    for item in hub.ls():
      hub.messenger.send("note", "{0} - {1}".format(item[0], item[1]))

  elif args["init"]:
    # Help out with initializing a new project
    # Start by printing a nice welcome message!
    print(hub.messenger.welcome(cosmid.__version__))

    q = "[{}]".format(colored("?", "green"))

    # Get user email for logging in to some FTP servers
    promt = q + colored(" Email adress (FTP login): ".format(q), "cyan")
    email = raw_input(promt)
    if email:
      hub.config.add("email", email)

    # Decide where to store cloned resources
    promt = q + colored(" Resource directory: (resources) ".format(q), "cyan")
    hub.config.add("directory", raw_input(promt) or "resources")

    # Suggest adding a sample resource
    promt = q + colored(" Add an example resource?: (y/N) ".format(q), "cyan")
    if raw_input(promt).lower() in ["y", "yes"]:
      hub.config.addResource("example", 2.5)

    # Save/Create the config file
    hub.config.save()

    # Just need some separation
    print()

    # Print an update that everything is done!
    hub.messenger.send("update", "Done! Now run: 'cosmid clone'")

  else:
    # -------------------------------------------------------
    #  Clone some resources!
    #  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #  N.B. Updating specific resources without version will
    #  replace existing releases with the latest version.
    # -------------------------------------------------------
    # Get user info about structuring files
    collapse = args["--collapse"] or hub.config.find("collapse", False)

    # We at least want to warn about not finding the project file
    if not hub.config_path.exists():
      message = "Couldn't find '{}'; run 'cosmid init'".format(hub.config_path)

      if args["--save"]:
        message_type = "error"
        sys.exit()

      else:
        message_type = "warning"

      hub.messenger.send(message_type, message)

    # Download resources specified from CLI
    if args["<resource_id>"]:
      resources = {}
      for resource_id in args["<resource_id>"]:
        # I add an extra ``None`` to be able to replace it with "*" for
        # entries without version #-tags that will be only 1-item lists.
        parts = resource_id.split("#") + [None]
        resources[parts[0]] = parts[1] or "latest"

    elif args["update"]:
      # We require the history file
      if not hub.history_path.exists():
        message = "Couldn't find any cloned resources"
        hub.messenger.send("error", message)
        sys.exit()

      # Add 'updateable' resources from history-file
      resources = hub.history.updateable()

    else:
      # Fetch all resources listed in "cosmid.yaml"
      resources = hub.config.find("resources", {})

    # -------------------------------------------------------
    #  Download each of the resources
    # -------------------------------------------------------
    for resource_id, target in resources.iteritems():

      resource, dl_paths, save_paths, version = hub.grab(resource_id, target,
                                                         collapse=collapse)

      if resource is None:
        # Something didn't add up... the user has been notified.
        continue

      else:
        # Path to actual save location for the resource
        if not hub.directory.exists():
          # Create it!
          hub.directory.mkdir()

        # Path to actual save location for the resource
        if collapse:
          # The user has choosen to save all files in the same base directory
          folder = path(hub.directory)

        else:
          # The user wants to separate each resource in it's corresponding
          # directory
          folder = path("{dest}/{id}".format(dest=hub.directory,
                                             id=resource.id))

        if not folder.exists() and not args["--dry"]:
          # Create it!
          folder.mkdir()

        # Download each file belonging to the resource
        for dl_path, save_path in zip(dl_paths, save_paths):

          # Prepare the user for what is going to happen
          fileSize = resource.ftp.fileSize(dl_path)
          message = ("Cloning: {path} - {size} MB"
                     .format(path=save_path, size=fileSize))

          if args["--dry"]:
            hub.messenger.send("ghost", message)

          else:
            hub.messenger.send("update", message)

            # Commit to the download!
            resource.ftp.commit(dl_path, save_path)

        if not (args["--dl-only"] and args["--dry"]):
          # Make the callback for post-cloning jobs
          resource.postClone(save_paths, folder, version)

        if args["--save"] or args["update"]:
          hub.messenger.send("update", "Processing downloaded files")
          # Add the user supplied data to the project YAML file
          hub.config.addResource(resource_id, target)

      # Save the config files for every resource
      if not args["--dry"]:
        # Save *over* the old "cosmid.yaml" file
        if hub.config_path.exists():
          hub.config.save()

        hub.history.save()


if __name__ == "__main__":
    # Always initiate the registry!
    hub = Registry()

    args = docopt(__doc__, version=hub.messenger.welcome(cosmid.__version__))
    main(args)
