#! /usr/bin/env python
# -*- coding: utf-8 -*-

import argparse
import re
import subprocess
import glob
import os
import sys


# Methods
def printAll(lines):
    for line in lines:
        print (line)


def buildG(lines):
    gs = {}
    for line in lines:
        if 'G-Group:' in line:
            a = map(int, re.findall(r'\d+', line))
            gs[a[0]] = a[1]
    return gs


def getC(lines):
    for line in lines:
        if 'Plan cost:' in line:
            return map(int, re.findall(r'\d+', line))[0]


def runFMM(command):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=False)
    outs, errs = p.communicate()
    if errs is not None:
        errlines = errs.splitlines()
        printAll(errlines)
        print 'Error Occurred = true'
        exit(1)
    else:
        return (getC(outs.splitlines()), buildG(outs.splitlines()))


def dual(i, c):
    return c-i


def sumStates(a, b, groups):
    result = 0
    for x in range(a, b):
        result += groups.get(x, 0)
    return result


if __name__ == "__main__":
    print('Program is running ..')
    # Read Arguments
    parser = argparse.ArgumentParser(
        description='Computes the weighted vertex cover.')
    parser.add_argument('problem', metavar='p', type=str,
                        nargs='?', const=1, default='/driverlog/p01.pddl',
                        help='The problem file.')
    parser.add_argument('algo', metavar='a', type=str,
                        nargs='?', const=1, default='lmcut',
                        help='The applied algorithm.')
    parser.add_argument('fast_downward', metavar='fd', type=str,
                        nargs='?', const=1, default='DOWNWARD_REPO',
                        help='Environment variable for the fast downward repo.')
    parser.add_argument('benchmark', metavar='bm', type=str,
                        nargs='?', const=1, default='DOWNWARD_BENCHMARKS',
                        help='Environment variable for the benchmark.')
    args = parser.parse_args()

    # Build command
    fd = os.getenv(args.fast_downward)
    benchmark = os.getenv(args.benchmark)
    command = [fd + '/fast-downward.py']
    fmmF = ['--search',
            'fmm(' + args.algo + ', b_eval=' + args.algo +
            '(transform=backward), p=1, print_g_groups=true)']
    fmmB = ['--search',
            'fmm(' + args.algo + ', b_eval=' + args.algo +
            '(transform=backward), p=0, print_g_groups=true)']
    fullCommand = command + [benchmark + args.problem] + fmmF

    # Gather g-value groups
    print('Running forward search..')
    cF, gF = runFMM(fullCommand + fmmF)
    print(gF)
    print('Running backward search..')
    cB, gB = runFMM(fullCommand + fmmB)
    print(gB)

    if cB != cF:
        print('Warning: ' + str(cF) + ' != ' + str(cB))
        exit(1)
    else:
        print('C* = ' + str(cF))
        c = cF

    if c is None:
        print('Warning: C* is None')
        exit(1)

    print('Computing different vertex covers ..')
    i = 0
    i_min = 0
    j = dual(i, c)
    WVC = sumStates(0, i, gF) + sumStates(0, j, gB)
    minWVC = WVC
    print('WVC (' + str('%.2f' % ((1.0*i)/c)) + '): ' + str(WVC))
    while i < c:
        WVC += sumStates(i, i+1, gF)
        WVC -= sumStates(j-1, j, gB)
        i += 1
        j -= 1
        print 'WVC (' + str('%.2f' % ((1.0*i)/c)) + '): ' + str(WVC)
        if WVC < minWVC:
            minWVC = WVC
            i_min = i
    print('WVC = ' + str(minWVC))
    print('p* = ' + str((1.0*i_min)/c))
    print('Program is finished!')
