# -*- coding: utf-8 -*-
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.

import libear
from . import call_and_report
import unittest

import os.path
import string
import glob


def prepare_cdb(name, target_dir):
    target_file = 'build_{0}.json'.format(name)
    this_dir, _ = os.path.split(__file__)
    path = os.path.normpath(os.path.join(this_dir, '..', 'src'))
    source_dir = os.path.join(path, 'compilation_database')
    source_file = os.path.join(source_dir, target_file + '.in')
    target_file = os.path.join(target_dir, 'compile_commands.json')
    with open(source_file, 'r') as in_handle:
        with open(target_file, 'w') as out_handle:
            for line in in_handle:
                temp = string.Template(line)
                out_handle.write(temp.substitute(path=path))
    return target_file


def run_analyzer(directory, cdb, args):
    cmd = ['analyze-build', '--cdb', cdb, '--output', directory] \
        + args
    return call_and_report(cmd, [])


class OutputDirectoryTest(unittest.TestCase):
    def test_regular_keeps_report_dir(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('regular', tmpdir)
            exit_code, reportdir = run_analyzer(tmpdir, cdb, [])
            self.assertTrue(os.path.isdir(reportdir))

    def test_clear_deletes_report_dir(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('clean', tmpdir)
            exit_code, reportdir = run_analyzer(tmpdir, cdb, [])
            self.assertFalse(os.path.isdir(reportdir))

    def test_clear_keeps_report_dir_when_asked(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('clean', tmpdir)
            exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--keep-empty'])
            self.assertTrue(os.path.isdir(reportdir))


class ExitCodeTest(unittest.TestCase):
    def test_regular_does_not_set_exit_code(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('regular', tmpdir)
            exit_code, __ = run_analyzer(tmpdir, cdb, [])
            self.assertFalse(exit_code)

    def test_clear_does_not_set_exit_code(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('clean', tmpdir)
            exit_code, __ = run_analyzer(tmpdir, cdb, [])
            self.assertFalse(exit_code)

    def test_regular_sets_exit_code_if_asked(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('regular', tmpdir)
            exit_code, __ = run_analyzer(tmpdir, cdb, ['--status-bugs'])
            self.assertTrue(exit_code)

    def test_clear_does_not_set_exit_code_if_asked(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('clean', tmpdir)
            exit_code, __ = run_analyzer(tmpdir, cdb, ['--status-bugs'])
            self.assertFalse(exit_code)

    def test_regular_sets_exit_code_if_asked_from_plist(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('regular', tmpdir)
            exit_code, __ = run_analyzer(
                tmpdir, cdb, ['--status-bugs', '--plist'])
            self.assertTrue(exit_code)

    def test_clear_does_not_set_exit_code_if_asked_from_plist(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('clean', tmpdir)
            exit_code, __ = run_analyzer(
                tmpdir, cdb, ['--status-bugs', '--plist'])
            self.assertFalse(exit_code)


class OutputFormatTest(unittest.TestCase):
    @staticmethod
    def get_html_count(directory):
        return len(glob.glob(os.path.join(directory, 'report-*.html')))

    @staticmethod
    def get_plist_count(directory):
        return len(glob.glob(os.path.join(directory, 'report-*.plist')))

    def test_default_creates_html_report(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('regular', tmpdir)
            exit_code, reportdir = run_analyzer(tmpdir, cdb, [])
            self.assertTrue(
                os.path.exists(os.path.join(reportdir, 'index.html')))
            self.assertEqual(self.get_html_count(reportdir), 2)
            self.assertEqual(self.get_plist_count(reportdir), 0)

    def test_plist_and_html_creates_html_report(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('regular', tmpdir)
            exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--plist-html'])
            self.assertTrue(
                os.path.exists(os.path.join(reportdir, 'index.html')))
            self.assertEqual(self.get_html_count(reportdir), 2)
            self.assertEqual(self.get_plist_count(reportdir), 5)

    def test_plist_does_not_creates_html_report(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('regular', tmpdir)
            exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--plist'])
            self.assertFalse(
                os.path.exists(os.path.join(reportdir, 'index.html')))
            self.assertEqual(self.get_html_count(reportdir), 0)
            self.assertEqual(self.get_plist_count(reportdir), 5)


class FailureReportTest(unittest.TestCase):
    def test_broken_creates_failure_reports(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('broken', tmpdir)
            exit_code, reportdir = run_analyzer(tmpdir, cdb, [])
            self.assertTrue(
                os.path.isdir(os.path.join(reportdir, 'failures')))

    def test_broken_does_not_creates_failure_reports(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('broken', tmpdir)
            exit_code, reportdir = run_analyzer(
                tmpdir, cdb, ['--no-failure-reports'])
            self.assertFalse(
                os.path.isdir(os.path.join(reportdir, 'failures')))


class TitleTest(unittest.TestCase):
    def assertTitleEqual(self, directory, expected):
        import re
        patterns = [
            re.compile(r'<title>(?P<page>.*)</title>'),
            re.compile(r'<h1>(?P<head>.*)</h1>')
        ]
        result = dict()

        index = os.path.join(directory, 'index.html')
        with open(index, 'r') as handler:
            for line in handler.readlines():
                for regex in patterns:
                    match = regex.match(line.strip())
                    if match:
                        result.update(match.groupdict())
                        break
        self.assertEqual(result['page'], result['head'])
        self.assertEqual(result['page'], expected)

    def test_default_title_in_report(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('broken', tmpdir)
            exit_code, reportdir = run_analyzer(tmpdir, cdb, [])
            self.assertTitleEqual(reportdir, 'src - analyzer results')

    def test_given_title_in_report(self):
        with libear.TemporaryDirectory() as tmpdir:
            cdb = prepare_cdb('broken', tmpdir)
            exit_code, reportdir = run_analyzer(
                tmpdir, cdb, ['--html-title', 'this is the title'])
            self.assertTitleEqual(reportdir, 'this is the title')
