#!/usr/bin/env python3

import argparse
import datetime
from hashlib import sha1
from pathlib import Path
import subprocess
import shutil
from textwrap import fill
import tempfile

from git import Repo
import pytz
import sarge
from slugify import slugify
import yaml


def is_jekyll_root(path: Path):
    return (path / "_config.yml").exists()


def hash_file(filename: Path) -> str:

    # Git-like SHA1 hashing

    filesize = filename.stat().st_size

    with filename.open() as handle:
        data = handle.read()

    contents = "blob " + str(filesize) + "\0" + data
    file_hash = sha1(contents.encode())

    return file_hash.hexdigest()


def perform_commit(filepath: Path, title: str=None,
                   draft: bool=False) -> None:

    import os
    repo = Repo(os.curdir)  # FIXME
    repo.index.add(str(filepath))

    if not draft:
        message = "New post: {}".format(title)
    else:
        message = "New draft: {}".format(title)

    message = fill(message, width=78)

    repo.commit(message)
    repo.remotes.origin.push()


def create_new_post(title: str, categories: list=None, tags: list=None,
                    post_metadata: dict=None, comments: bool=True,
                    draft: bool=False) -> Path:

    title_slug = slugify(title)
    current_time = datetime.datetime.now(pytz.timezone("Europe/Rome"))
    date_slug = current_time.date().isoformat()
    formatted_date = current_time.strftime("%Y-%m-%d %H:%M:%S%z")

    metadata = dict(title=title, comments=comments, layout="page")

    if not draft:
        metadata["date"] = formatted_date
        filename = "{0}-{1}.markdown".format(date_slug, title_slug)
    else:
        filename = "{0}.markdown".format(title_slug)

    if categories is not None:
        metadata["categories"] = categories
    else:
        metadata["categories"] = ["General"]

    if tags is not None:
        metadata["tags"] = tags

    if post_metadata is not None:
        for key, value in post_metadata.items():
            metadata[key] = value

    if not draft:
        final_path = Path("_posts") / filename
    else:
        final_path = Path("_drafts") / filename

    with tempfile.NamedTemporaryFile(mode="wt", suffix=".md") as temp:

        temp_path = Path(temp.name)

        temp.write("---\n")
        yaml.safe_dump(metadata, temp, default_flow_style=False)
        temp.write("---\n")
        temp.flush()

        pre_edit_hash = hash_file(temp_path)
        print("Save and close the editor after writing the post.")
        subprocess.check_call("/usr/bin/kate {}".format(temp.name),
                              shell=True)
        post_edit_hash = hash_file(temp_path)

        if pre_edit_hash == post_edit_hash:
            print("No post content. Aborting.")
            return

        shutil.copy(temp.name, str(final_path))

    return (final_path)


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument("-t", "--tags", nargs="+",
                        help="Post tags (space separated)")
    parser.add_argument("-c", "--categories", nargs="+",
                        help="Post categories (space separated)")
    parser.add_argument("--disable_comments", action="store_false",
                        help="Disable comments for the post")
    parser.add_argument("--commit", action="store_true",
                        help="Commit and push to the remote repository")
    parser.add_argument("--draft", action="store_true",
                        help="Create the post as draft")
    parser.add_argument("title", help="Title of the new post")

    options = parser.parse_args()

    if not is_jekyll_root(Path("./")):
        raise FileNotFoundError("Jekyll root not found.")

    path = create_new_post(options.title, options.categories, options.tags,
                           comments=options.disable_comments,
                           draft=options.draft)

    if path is None:
        exit(1)

    print("Created new post {}.".format(path.name))

    if options.commit:
        print("Committing to upstream repository...")
        perform_commit(path, options.title, options.draft)
        
    print("Done.")


if __name__ == "__main__":
    main()