#!/usr/bin/env python import argparse import collections import os import shutil from pathlib import Path import oyaml as yaml

class MyDumper(yaml.Dumper):

def increase_indent(self, flow=False, indentless=False):
    return super(MyDumper, self).increase_indent(flow, False)

def load_yaml(filepath):

'''
Load the content of a YAML file to a dictionary

:param filepath: path to a YAML file

:return: dictionary with the content of the YAML file
'''
with open(filepath, "r") as m_file:
    content = yaml.load(m_file)
return content

def save_to_yaml(content, filepath):

'''
Save a dictionary to a YAML file

:param content: dictionary to save
:param filepath: path an output YAML file
'''
with open(filepath, 'w') as stream:
    yaml.dump(content,
              stream,
              Dumper=MyDumper,
              indent=2,
              default_flow_style=False,
              default_style='',
              explicit_start=True)

def change_topic_name(filepath):

'''
Change the topic name in the top metadata of a file

:param filepath: path to index.md, tutorial.md or slides.html
'''
with open(filepath, "r") as in_f:
    content = in_f.read()

content = content.replace("your_topic", args.topic_name)
content = content.replace("your_tutorial_name", "tutorial1")

with open(filepath, 'w') as out_f:
    out_f.write(content)

def create_topic(args, topic_dir, template_dir):

'''
Create the skeleton of a new topic:

1. copy templates
2. update the index.md to match your topic's name
3. fill the metadata
4. add a symbolic link to the metadata.yaml from the metadata folder

:param args: arguments of the script
:param topic_dir: path to the new topic directory
:param template_dir: path to the template directory for a new topic
'''
# copy templates
shutil.copytree(template_dir, topic_dir)

# update the index.md to match your topic's name
index_path = topic_dir / Path("index.md")
change_topic_name(index_path)

# update the metadata file
metadata_path = topic_dir / Path("metadata.yaml")

metadata = load_yaml(metadata_path)
metadata['name'] = args.topic_name
metadata['title'] = args.topic_title
metadata['type'] = args.topic_target
metadata['summary'] = args.topic_summary

save_to_yaml(metadata, metadata_path)

# update the metadata in top of tutorial.md and slides.html
tuto_path = topic_dir / Path("tutorials") / Path("tutorial1")
hand_on_path = tuto_path / Path("tutorial.md")
change_topic_name(hand_on_path)
slides_path = tuto_path / Path("slides.html")
change_topic_name(slides_path)

# add a symbolic link to the metadata.yaml
os.chdir(Path("metadata"))
os.symlink(Path("..") / metadata_path, Path("{}.yaml".format(args.topic_name)))
os.chdir(Path(".."))

def update_tuto_file(filepath, keep, args):

'''
Update or delete a tutorial (hands-on or slide) file

:param filepath: path to hands-on or slide file
:param keep: boolean indicated to keep it or not
:param args: arguments of the script
'''
if keep:
    with open(filepath, "r") as in_f:
        content = in_f.read()

    content = content.replace("your_topic", args.topic_name)
    content = content.replace("your_tutorial_name", args.tutorial_name)

    with open(filepath, 'w') as out_f:
        out_f.write(content)

elif filepath.is_file():
    filepath.unlink()

def update_tutorial(args, tuto_dir, topic_dir):

'''
Update the metadata information of a tutorial

:param args: arguments of the script
:param tuto_dir: path to the new tutorial directory
:param topic_dir: path to the new topic directory
'''
# update the metadata file to add the new tutorial
metadata_path = topic_dir / Path("metadata.yaml")

metadata = load_yaml(metadata_path)
found = False
for mat in metadata["material"]:
    if mat["name"] == args.tutorial_name:
        mat["name"] = args.tutorial_name
        mat["title"] = args.tutorial_title
        mat["hands_on"] = args.tutorial_hands_on
        mat["slides"] = args.tutorial_slides
        found = True

if not found:
    new_mat = collections.OrderedDict()
    new_mat["title"] = args.tutorial_title
    new_mat["name"] = args.tutorial_name
    new_mat["type"] = 'tutorial'
    new_mat["zenodo_link"] = ''
    new_mat["hands_on"] = args.tutorial_hands_on
    new_mat["slides"] = args.tutorial_slides
    new_mat["workflows"] = False
    new_mat["galaxy_tour"] = False
    new_mat["questions"] = ['', '']
    new_mat["objectives"] = ['', '']
    new_mat["time_estimation"] = '1d/3h/6h'
    new_mat["key_points"] = ['', '']
    new_mat["contributors"] = ['contributor1', 'contributor2']
    metadata["material"].append(new_mat)

save_to_yaml(metadata, metadata_path)

# update the metadata in top of tutorial.md or remove it if not needed
hand_on_path = tuto_dir / Path("tutorial.md")
update_tuto_file(hand_on_path, args.tutorial_hands_on, args)

# update the metadata in top of slides.md or remove it if not needed
slides_path = tuto_dir / Path("slides.html")
update_tuto_file(slides_path, args.tutorial_slides, args)

def create_tutorial(args, tuto_dir, topic_dir, template_dir):

'''
Create the skeleton of a new tutorial

:param args: arguments of the script
:param tuto_dir: path to the new tutorial directory
:param topic_dir: path to the new topic directory
:param template_dir: path to the template directory for a new tutorial
'''
# copy or rename templates
template_tuto_path = topic_dir / Path("tutorials") / Path("tutorial1")
if template_tuto_path.is_dir():
    template_tuto_path.rename(tuto_dir)
else:
    shutil.copytree(template_dir, tuto_dir)

# fill the metadata of the new tutorial
update_tutorial(args, tuto_dir, topic_dir)

if __name__ == '__main__':

parser = argparse.ArgumentParser(description='Create the skeleton for a new topic and/or a new tutorial')
parser.add_argument('--topic_name', help='Name (directory name) of the topic to create or in which the tutorial should be create', required=True)
parser.add_argument('--topic_title', help='Title of the topic to create', default='Title of the topic', required=False)
parser.add_argument('--topic_target', help='Target of the topic', default='use', choices=['use', 'admin-dev', 'instructors'], required=False)
parser.add_argument('--topic_summary', help='Summary of the topic', default='Summary of the topic', required=False)
parser.add_argument('--tutorial_name', help='Name (directory name) of the new tutorial to create (it will be the directory name)', required=False)
parser.add_argument('--tutorial_title', help='Title of the new tutorial', default='Title of the tutorial', required=False)
parser.add_argument('--hands_on', help='Hands-on for the new tutorial', dest='tutorial_hands_on', action='store_true')
parser.set_defaults(tutorial_hands_on=True)
parser.add_argument('--slides', help='Slides for the new tutorial', dest='tutorial_slides', action='store_true')
parser.set_defaults(tutorial_slides=False)
args = parser.parse_args()

template_dir = Path("templates")

topic_dir = Path("topics") / Path(args.topic_name)
if not topic_dir.is_dir():
    print("The topic {} does not exist. It will be created".format(args.topic_name))
    create_topic(args, topic_dir, template_dir)

if args.tutorial_name:
    tuto_dir = topic_dir / Path("tutorials") / Path(args.tutorial_name)
    if not tuto_dir.is_dir():
        template_dir = template_dir / Path("tutorials") / Path("tutorial1")
        print("The tutorial {} in topic {} does not exist. It will be created.".format(args.tutorial_name, args.topic_name))
        create_tutorial(args, tuto_dir, topic_dir, template_dir)
    else:
        print("The tutorial {} in topic {} already exists. It will be updated with the other arguments".format(args.tutorial_name, args.topic_name))
        update_tutorial(args, tuto_dir, topic_dir)