<?php

use Github\Client;
use Gitlab\Client as LabClient;
use PhpMimeMailParser\Parser;

include_once(__DIR__ . '/vendor/autoload.php');
include(__DIR__ . '/src/Repo.php');
include(__DIR__ . '/src/GithubRepo.php');
include(__DIR__ . '/src/GitlabRepo.php');

class Issuer
{
    public function __construct($mail)
    {
        try {
            $title =  $mail->getHeader('subject');
            $body = $mail->getMessageBody('text');
            $body = $this->stripQuotes($body);
            $from = array_pop($mail->getAddresses('from'));
            $body = 'Email from: ' . $from['address'] . "\n\n" . $body;
            $title = str_ireplace('RE:', '', $title);
            $title = trim($title);
            list($repo, $type) = $this->getRepo($mail);

            $github = $this->getProxy($type);
            $found = $github->findIssue($title, $repo);
            if ($found !== false) {
                $github->addToIssue(['repo'=>$repo, 'id'=>$found['id'], 'body'=>$body]);
            } else {
                $github->createIssue(['repo'=>$repo, 'title'=>$title, 'body'=>$body]);
            }
        } catch (Exception $ex) {
            $this->logFailure($ex, $body);
        }
    }

    private function getProxy($type)
    {
        if ($type == 'Github') {
            $github = new Issuer\GithubRepo();
            $github->authenticate(['token'=>'74d9bc6abbff46faf1d7c895bd3347417c1a0291']);

            return $github;
        }

        $gitlab = new Issuer\GitlabRepo();
        $gitlab->authenticate(['token'=>'xySxdG1XbQnExSsdGDJP']);

        return $gitlab;
    }

    private function logFailure($ex,$body)
    {
        $fp = fopen(__DIR__ . '/failed.log', 'a');
        fwrite($fp, date('r') . ': Failed with ' . $ex->getMessage() . "\n");
        fwrite($fp, "Message:\n{$body}\n\n");
        fwrite($fp, "Traceback:\n" . $ex->getTraceAsString() . "\n\n");
        fclose($fp);
    }

    private function stripQuotes($body)
    {
        $body = explode("\n", $body);
        $body = array_reverse($body);
        $quotesDone = false;
        $ret = [];
        foreach ($body as $line) {
            $line = trim($line);
            if ($line != '' && $line[0] != '>') {
                $quotesDone = true;
            }
            if (!$quotesDone && $line == '') {
                continue;
            }
            if (!$quotesDone && $line != '' && $line[0] == '>') {
                continue;
            }

            $ret[] = $line;
        }
        $ret = array_reverse($ret);

        return implode("\n", $ret);
    }

    private function getRepo($mail)
    {
        foreach (['from', 'to', 'cc'] as $addrType) {
            foreach ($mail->getAddresses($addrType) as $addr) {
                if (!strpos($addr['address'], '@')) continue;
                if ($addr['address'] == 'root@rivervalleymarket.coop') continue;
                list($name, $domain) = explode('@', $addr['address'], 2);
                $mapped = $this->domainToRepo($domain);
                if ($mapped !== false) {
                    return $mapped;
                }
            }
        }

        return ['Internal', 'Gitlab'];
    }

    private function domainToRepo($domain)
    {
        switch (strtolower($domain)) {
            case 'rivervalley.coop':
            case 'rivervalleymarket.coop':
                return ['RVC', 'Gitlab'];
            case 'alberta.coop':
            case 'albertagrocery.coop':
                return ['Alberta', 'Gitlab'];
            case 'wirth.coop':
                return ['Wirth', 'Gitlab'];
            case 'harvest.coop':
                return ['Harvest', 'Gitlab'];
            case 'ourtable.us':
                return ['Our-Table', 'Gitlab'];
            case 'rutlandcoop.com':
            case 'castleton.edu':
            case 'csc.vsc.edu':
                return ['Rutland', 'Gitlab'];
            case 'elfco.coop':
                return ['ELFCO', 'Gitlab'];
            case 'nolafood.coop':
                return ['NOFC', 'Gitlab'];
            case 'macombfoodcoop.net':
                return ['Macomb', 'Gitlab'];
            case 'berryroadfood.coop':
                return ['Berry Road', 'Gitlab'];
            case 'southphillyfood.coop':
            case 'southphillyfoodcoop.org':
                return ['south-philly', 'Gitlab'];
        }

        return false;
    }

    public static function test()
    {
        $repo = 'Internal';
        $type = 'Gitlab';
        $github = new Issuer\GitlabRepo();
        $github->authenticate(['token'=>'xySxdG1XbQnExSsdGDJP']);
        $found = $github->findIssue('test gitlab');
        if ($found) {
            $github->addToIssue(['repo'=>$repo, 'id'=>$found['id'], 'body'=>'a followup message']);
        } else {
            $github->createIssue(['repo'=>$repo, 'title'=>'test gitlab', 'body'=>'a new message']);
        }
    }
}

ini_set('log_errors', 1);
ini_set('error_log', '/tmp/issuer.log');
$parser = new Parser();
$parser->setStream(fopen('php://stdin', 'r'));
$issuer = new Issuer($parser);

