#!/usr/bin/env python3
import os
import shutil
import argparse
import logging
from snakemake_rules import SNAKEMAKE_RULES_PATH
from snakemake.workflow import Workflow
from snakemake.exceptions import print_exception

FORMAT = '%(levelname)s: %(asctime)-15s: %(message)s'
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__file__)

def sync_file(source, dest, dryrun=False):
    """Sync file source to dest"""
    if not os.path.exists(v):
        if dryrun:
            logger.info("DRY_RUN: Copying rule '{}' to '{}'".format(source, dest))
        else:
            if not os.path.exists(os.path.dirname(dest)):
                os.makedirs(os.path.dirname(dest))
            logger.info("Copying rule '{}' to '{}'".format(source, dest))
            shutil.copy2(source, dest)
    else:
        srctime = os.path.getmtime(source)
        desttime = os.path.getmtime(dest)
        if (desttime > srctime):
            if dryrun:
                logger.info("DRY_RUN: Updating rule '{}' to '{}'".format(source, dest))
            else:
                logger.info("Updating rule '{}' to '{}'".format(source, dest))
                shutil.copy2(source, dest)
        else:
            if dryrun:
                logger.info("DRY_RUN: rule '{}' up to date".format(dest))
            else:
                logger.info("rule '{}' up to date".format(dest))


parser = argparse.ArgumentParser("Copy/sync rules to a given directory")
parser.add_argument('Snakefile', help="Snakefile to import")
parser.add_argument('-n', '--dry-run', action="store_true", help="Dry run")
parser.add_argument('-d', '--outdir', action="store", default=os.curdir,
                    help="Snakefile to import")
args = parser.parse_args()

snakefile = os.path.abspath(args.Snakefile)

workflow = Workflow(snakefile=snakefile)

try:
    workflow.include(snakefile,
                     overwrite_first_rule=True,
                     print_compilation=False)
    workflow.check()
except (Exception, BaseException) as ex:
    print_exception(ex, workflow.linemaps)
    success = False


# Map the rules included from snakemake_rules
DEST=args.outdir
rules = {x:os.path.join(DEST, os.path.relpath(x, SNAKEMAKE_RULES_PATH)) for x in workflow.included if x.startswith(SNAKEMAKE_RULES_PATH)}

# Copy rules to outdir
for k, v in rules.items():
    sync_file(k, v, args.dry_run)

@@ -447,17 +447,20 @@
 .exists(
-v
+dest
 ):%0A     
@@ -1366,16 +1366,332 @@
 dest))%0A%0A
+# Snakemake rules dictionary%0Apath = SNAKEMAKE_RULES_PATH%0Afilters = ('.rules', '.rule', '.settings')%0Asnakemake_rule_dict = %7B%7D%0Afor path, dirs, files in os.walk(path):%0A    for f in files:%0A        if f.endswith(filters):%0A            snakemake_rule_dict%5Bos.path.splitext(os.path.basename(f))%5B0%5D%5D = os.path.join(path, f)%0A%0A
 %0Aparser 
@@ -2386,17 +2386,16 @@
  False%0A%0A
-%0A
 # Map th
@@ -2449,16 +2449,26 @@
 .outdir%0A
+%0Aincluded_
 rules = 
@@ -2597,17 +2597,16 @@
 _PATH)%7D%0A
-%0A
 # Copy r
@@ -2632,16 +2632,25 @@
 k, v in 
+included_
 rules.it
@@ -2690,8 +2690,454 @@
 ry_run)%0A
+%0Aworkflow_rules = %7Br.name:r for r in workflow.rules%7D%0A%0Aleftover_rules = set(workflow_rules.keys()).difference(included_rules.keys())%0Afor r in leftover_rules:%0A    if r in list(snakemake_rule_dict.keys()):%0A        dest = os.path.join(DEST, os.path.relpath(snakemake_rule_dict%5Br%5D, SNAKEMAKE_RULES_PATH))%0A        sync_file(snakemake_rule_dict%5Br%5D, dest, args.dry_run)%0A    else:%0A        logger.warn(%22No such rule '%7B%7D' in snakemake_rule_dict%22.format(r))%0A

Add functionality for inlined rules