<commit_before><?php

namespace Jira;

use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Cache\CacheProvider;
use GuzzleHttp\Exception\ClientException;
use JiraApi\Clients\IssueClient;
use JiraApi\Clients\ProjectClient;
use JiraApi\Search\SearchBuilder;
use Psr\Log\LoggerInterface;

/**
 * @author <NAME> <<EMAIL>>
 */
class Jira
{

    use Logger;
    use Cache;
    
    /**
     * @var ProjectClient
     */
    private $projectClient;

    /**
     * @var IssueClient
     */
    private $issueClient;
    
    /**
     * @var \stdClass
     */
    private $config;

    public function __construct(\stdClass $config, LoggerInterface $logger, CacheProvider $cacheProvider = null)
    {
        $this->config = $config;
        $this->projectClient = new ProjectClient($config->url, $config->username, $config->password);
        $this->issueClient = new IssueClient($config->url, $config->username, $config->password);
        
        $this->logger = $logger;
        $this->cacheProvider = $cacheProvider ? $cacheProvider : new ArrayCache();
    }
    
    public function verifyUser()
    {
        try {
            // TODO: ask password from INPUT
            $this->issueClient->getRequest(sprintf('user?username=%s', $this->config->username))->json();
            $this->debug(sprintf('%s ok', $this->config->url));
        } catch(ClientException $e) {
            $this->error($e->getMessage());
            die('Please check config file.');
        }
    }

    public function copyWorklogs(array $worklogs, $project, $author)
    {
        $this->debug('', 1);

        foreach ($worklogs as $worklog) 
        {
            $summary = $worklog['issue']['fields']['summary'];
            $issue = $this->findIssue($summary, $project);
            if (!$issue) {
                try {
                    $issue = $this->createIssue($summary, $project);
                } catch (\Exception $e) {
                    $this->debug($e->getMessage());
                    continue;
                }
            }

            $copied = false;
            $logs = $this->getWorklogs($issue['key']);
            foreach ($logs['worklogs'] as $log) 
            {
                // only from author
                if ($log['author']['name'] != $author) {
                    continue;
                }
                
                // check if already copied
                $copied = $this->isCopied($log, $worklog);
                if ($copied) {
                    break;
                }
            }

            if (!$copied) {
                $this->createWorklog($issue['key'], $worklog);
            }
        }
        
        $this->debug('done', 1);
    }
    
    protected function isCopied(array $worklog1, array $worklog2)
    {
        // compare comments
        if ($worklog1['comment'] != $worklog2['comment']) {
            return false;
        }
        
        // compare time spent
        if ($worklog1['timeSpentSeconds'] != $worklog2['timeSpentSeconds']) {
            return false;
        }
        
        // compare dates
        $d1 = new \DateTime($worklog1['started']);
        $d2 = new \DateTime($worklog2['started']);
        $tz = new \DateTimeZone('Asia/Manila');
        $d1->setTimezone($tz);
        $d2->setTimezone($tz);
        if ($d1->format('Y-m-d') != $d2->format('Y-m-d')) {
            return false;
        }
        
        return true;
    }

    public function createWorklog($idOrKey, array $worklog)
    {
        $this->info(sprintf('********* %s ********', $idOrKey), 3);

        $data = array(
            'comment' => $worklog['comment'],
            'timeSpentSeconds' => $worklog['timeSpentSeconds'],
            'started' => $worklog['started'],
        );
        
        $progress = $worklog['issue']['fields']['progress'];
        $remaining = $progress['total'] - $progress['progress'];
        
        $this->issueClient->createWorklog($idOrKey, $data, 'new', sprintf('%dm', $remaining/60));
    }

    public function createIssue($summary, $projectKey)
    {
        $this->info(sprintf('++++++++++ %s ++++++++++', $summary), 2);
        
        $project = $this->getProject($projectKey);
        if (!$project) {
            throw new \Exception(sprintf('Project %s not found!', $projectKey));
        }
        $data = array(
            'fields' => [
                'project' => [
                    'id' => $project['id'],
                ],
                'summary' => $summary,
                'issuetype' => [
                    'id' => 3, // FIXME: Task
                ],
                // TODO: description -> Duplicate (link)
            ]
        );

        $result = $this->issueClient->create($data)->json();
        return $result;
    }

    public function findIssue($summary, $project)
    {
        $this->debug($summary, 2);

        $cacheId = sprintf('%s_issue_%s', $project, md5($summary));
        if (($cached = $this->getCache($cacheId))) {<commit_msg>Updating description<commit_after><?php

namespace Jira;

use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Cache\CacheProvider;
use GuzzleHttp\Exception\ClientException;
use JiraApi\Clients\IssueClient;
use JiraApi\Clients\ProjectClient;
use JiraApi\Search\SearchBuilder;
use Psr\Log\LoggerInterface;

/**
 * @author <NAME> <<EMAIL>>
 */
class Jira
{

    use Logger;
    use Cache;
    
    /**
     * @var ProjectClient
     */
    private $projectClient;

    /**
     * @var IssueClient
     */
    private $issueClient;
    
    /**
     * @var \stdClass
     */
    private $config;

    public function __construct(\stdClass $config, LoggerInterface $logger, CacheProvider $cacheProvider = null)
    {
        $this->config = $config;
        $this->projectClient = new ProjectClient($config->url, $config->username, $config->password);
        $this->issueClient = new IssueClient($config->url, $config->username, $config->password);
        
        $this->logger = $logger;
        $this->cacheProvider = $cacheProvider ? $cacheProvider : new ArrayCache();
    }
    
    public function verifyUser()
    {
        try {
            // TODO: ask password from INPUT
            $this->issueClient->getRequest(sprintf('user?username=%s', $this->config->username))->json();
            $this->debug(sprintf('%s ok', $this->config->url));
        } catch(ClientException $e) {
            $this->error($e->getMessage());
            die('Please check config file.');
        }
    }

    public function copyWorklogs(array $worklogs, $project, $author)
    {
        $this->debug('', 1);

        foreach ($worklogs as $worklog) 
        {
            $summary = $worklog['issue']['fields']['summary'];
            $issue = $this->findIssue($summary, $project);
            if (!$issue) {
                try {
                    $issue = $this->createIssue($summary, $project, $worklog['issue']);
                } catch (\Exception $e) {
                    $this->debug($e->getMessage());
                    continue;
                }
            }

            $copied = false;
            $logs = $this->getWorklogs($issue['key']);
            foreach ($logs['worklogs'] as $log) 
            {
                // only from author
                if ($log['author']['name'] != $author) {
                    continue;
                }
                
                // check if already copied
                $copied = $this->isCopied($log, $worklog);
                if ($copied) {
                    break;
                }
            }

            if (!$copied) {
                $this->createWorklog($issue['key'], $worklog);
            }
        }
        
        $this->debug('done', 1);
    }
    
    protected function isCopied(array $worklog1, array $worklog2)
    {
        // compare comments
        if ($worklog1['comment'] != $worklog2['comment']) {
            return false;
        }
        
        // compare time spent
        if ($worklog1['timeSpentSeconds'] != $worklog2['timeSpentSeconds']) {
            return false;
        }
        
        // compare dates
        $d1 = new \DateTime($worklog1['started']);
        $d2 = new \DateTime($worklog2['started']);
        $tz = new \DateTimeZone('Asia/Manila');
        $d1->setTimezone($tz);
        $d2->setTimezone($tz);
        if ($d1->format('Y-m-d') != $d2->format('Y-m-d')) {
            return false;
        }
        
        return true;
    }

    public function createWorklog($idOrKey, array $worklog)
    {
        $this->info(sprintf('********* %s ********', $idOrKey), 3);

        $data = array(
            'comment' => $worklog['comment'],
            'timeSpentSeconds' => $worklog['timeSpentSeconds'],
            'started' => $worklog['started'],
        );
        
        $progress = $worklog['issue']['fields']['progress'];
        $remaining = $progress['total'] - $progress['progress'];
        
        $this->issueClient->createWorklog($idOrKey, $data, 'new', sprintf('%dm', $remaining/60));
    }

    public function createIssue($summary, $projectKey, array $issue)
    {
        $this->info(sprintf('++++++++++ %s ++++++++++', $summary), 2);
        
        $project = $this->getProject($projectKey);
        if (!$project) {
            throw new \Exception(sprintf('Project %s not found!', $projectKey));
        }
        list($d,) = explode('/rest/api', $issue['self']);
        
        $data = array(
            'fields' => [
                'project' => [
                    'id' => $project['id'],
                ],
                'summary' => $summary,
                'issuetype' => [
                    'id' => 3, // FIXME: Task
                ],
                'description' => sprintf('CopyLog %s/browse/%s', $d, $issue['key']),
            ]
        );
        
        $result = $this->issueClient->create($data)->json();
        return $result;
    }

    public function findIssue($summary, $project)
    {
        $this->debug($summary, 2);

        $cacheId = sprintf('%s_issue_%s', $project, md5($summary));
        if (($cached = $this->getCache($cacheId))) {
{'fraction_non_alphanumeric': 0.16658432961169845, 'fraction_numerical': 0.004545005434245628, 'mean_word_length': 1.75129111171514, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 117, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1410128', 'n_tokens_mistral': 2927, 'n_tokens_neox': 2841, 'n_words': 542}