#!/usr/bin/env python

"""
File for running the `ds` instructor tools.
"""

import os
import argparse
from dscreate.utils import *
from dscreate.create import *
from traitlets.config.loader import PyFileConfigLoader
from nbgrader.apps import NbGraderAPI

parser = argparse.ArgumentParser(description='Flatiron Data Science Instructor Tools')

parser.add_argument('command', choices=['create', 'generate',
                                        'share', 'edit'],
                    help='''

                    create    – Positional argument. 
                                This command splits a curriculum `index.ipynb` notebook into lesson and solution notebooks, 
                                and pushes the changes to github.  
                             
                             Default: An `index.ipynb` on a `curriculum` branch is split.
                                      The student facing cells of the notebook are placed in an `index.ipynb` file on the master branch
                                      The solution cells of the notebook are placed in an `index.ipynb` file on the solution branch
                            
                             -dir:   When this flag is used git branches are not used, and solution files are placed
                                     in a hidden folder called `.solution_files`. Instead of a `curriculum` branch,
                                     the lesson should developed in a `curriculum.ipynb` notebook.
                                     The student facing cells of the notebook are placed in an `index.ipynb` file within the cwd
                                     The solution cells are placed in an `index.ipynb` file within the `.solution_files` directory
                                     The `curriculum.ipynb` file is deleted. See `edit` for restoring the curriculum notebook.

                    generate  – Positional argument. 
                                This command is used to generate READMEs 
                                for the release and source notebooks of an nbgrader assignment. 

                               This command:
                                - Generates an assignment using the NbGrader API
                                - Converts the source notebook to markdown and saves as a README on the master branch
                                - Merges the master branch into the solution branch
                                - Converts the release notebook to mardown and saves as a README on the master branch
                                - Pushes changes

                    share     – Positional argument.
                                This command requires a third positional argument in the form of a github notebook url.
                                This comment adds to the user's clipboard, a link that opens a github notebook 
                                on an illumidesk server. 

                    edit      – Positional argument.
                                This command generates a `curriculum.ipynb` notebook using the files
                                inside the `.solution_files` directory. 
                    ''')

parser.add_argument('-dir', action='store_true', default=False, dest='dir',
                    help='''
                    'Optional argument. When used, a curriculum notebook will be split within the assignment directory rather than 
                    across branches. Solution files are placed in a .solution_files folder
                    within the cwd. This split method can be useful when compiling multiple lessons within a single directory. 
                    ''')


color = Color()                            
args = parser.parse_args()

# TODO add a begin command that allows sets up an assignment directory with the correct files. 
# if args.command == "begin":
#     begin()
#     print()
#     print(color.BOLD, color.CYAN, '💻 Lesson directory created! Curriculum materials should be developed in the curriculum.ipynb file!', color.END)
#     print()

if args.command == "create" and args.dir:
    splitter = SplitNotebook(filename='curriculum.ipynb')
    lesson_cells, solution_cells = splitter.split_notebooks()
    solution_dir = '.solution_files'
    if not os.path.isdir(solution_dir):
        os.mkdir(solution_dir)
    solution_path = os.path.join(solution_dir, 'index')
    splitter.write_notebook(solution_path, solution_cells)
    splitter.write_notebook('index', lesson_cells)
    os.remove("curriculum.ipynb")
    print()
    print(color.BOLD, color.CYAN, '📒 Solution and Lesson Notebooks have been created!', color.END)
    print()
    print(color.BOLD, color.GREEN, 'To access the curriculum notebook, run ds -curriculum', color.END)
    print()

elif args.command == "create":

    branches = os.path.join('.git', 'refs', 'heads')
    if 'curriculum' not in os.listdir(branches):
        raise ValueError('A curriculum branch must exist.')

    # Commit curriculum changes
    print('Commiting curriculum changes...')
    repo = GitModel()
    splitter = SplitNotebook()
    commit_msg = repo.get_commit_message()
    repo.add_and_commit(commit_msg)

    if 'master' not in os.listdir(branches):
        print('Creating a master branch...')
        solution = repo.create_head('master')
        origin = repo.remote()
        origin.push('master')

    if 'solution' not in os.listdir(branches):
        print('Creating a solution branch...')
        solution = repo.create_head('solution')
        origin = repo.remote()
        origin.push('solution')

    # Split notebook
    print('Splitting notebook...')
    lesson_cells, solution_cells = splitter.split_notebook()

    # Update master branch
    print('Updating master branch...')
    repo.git.checkout('master')
    repo.git.checkout('curriculum', '.')
    splitter.write_notebook('index', lesson_cells)
    generate_readme('index.ipynb', '.' + os.sep, 'README')
    repo.add_and_commit(commit_msg)

    # Update solution branch
    print('Updating solution branch...')
    repo.git.checkout('solution')
    repo.git.checkout('curriculum', '.')
    splitter.write_notebook('index', solution_cells)
    generate_readme('index.ipynb', '.' + os.sep, 'README')
    repo.add_and_commit(commit_msg)

    # Push changes
    print('Pushing changes to remote...')
    repo.git.push('origin', 'master')
    repo.git.push('origin', 'solution')
    repo.git.push('origin', 'curriculum')
    print('Complete!')

if args.command == "edit":
    generator = GenerateCurriculum()
    generator.main()
    print()
    print(color.BOLD, color.CYAN, '📒 Curriculum Notebook has been generated!', color.END)
    print()    

if args.command == "share":
    share = ShareNotebook()
    share.main(args.url)
    print()
    print(color.BOLD, color.CYAN, '📋 An Illumidesk link has been added to your clipboard!', color.END)
    print()

if args.command == 'generate':

    ASSIGNMENT = os.getcwd().split(os.sep)[-1]

    # create a config object to specify options for nbgrader
    top_directory = get_top_directory()
    config_path = os.path.join(top_directory, 'nbgrader_config.py')
    config_loader = PyFileConfigLoader(config_path)
    config = config_loader.load_config()
    config.pop('IncludeHeaderFooter', None)

    # Connect to api
    api = NbGraderAPI(config=config)

    # Generate Assignment
    print('Generating assignment...')
    results = api.generate_assignment(ASSIGNMENT)
    if not results['success']:
        raise ValueError(results['log'])

    # Generate source readme
    print('Generating source readme...')
    source_path = os.path.join(top_directory, 'source', ASSIGNMENT)
    source_notebook_path = os.path.join(source_path, 'index.ipynb')
    if not os.path.isfile(source_notebook_path):
        raise ValueError('The assignment notebook must be named index.ipynb')
    # Save source readme to master branch
    generate_readme(source_notebook_path, source_path, 'README')

    # Create a git interface
    repo = GitModel()

    # Create a solution branch if it doesn't exist
    if 'solution' not in os.listdir('.git/refs/heads'):
        print('Creating a solution branch...')
        solution = repo.create_head('solution')
        origin = repo.remote()
        origin.push('solution')

    # Commit changes to master branch
    repo.add_and_commit(commit_msg='Update source readme')
    
    # Merge master into solution
    repo.merge_solution()

    # Checkout master branch
    repo.git.checkout("master")

    # Create release readme
    print('Generating release readme...')
    release_path = os.path.join(top_directory, 'release', ASSIGNMENT)
    release_notebook_path = os.path.join(release_path, 'index.ipynb')

    # Save release readme to master branch
    generate_readme(release_notebook_path, source_path, 'README')

    # Commit changes to master branch
    repo.add_and_commit(commit_msg="Update release readme")

    # Push changes
    print('Pushing changes to master branch...')
    repo.git.push("origin", "master")
    repo.git.checkout("solution")
    print('Pushing changes to solution branch...')
    repo.git.push("origin", "solution")

    # End on master branch
    repo.git.checkout('master')

