#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# diffoscope: in-depth comparison of files, archives, and directories
#
# Copyright © 2016 Chris Lamb <lamby@debian.org>
#
# diffoscope is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# diffoscope is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with diffoscope.  If not, see <http://www.gnu.org/licenses/>.

import io
import os
import sys
import time
import argparse
import requests
import webbrowser


class TryDiffoscope(object):
    def __init__(self, args):
        self.args = args
        self.session = requests.Session()

    def main(self):
        response = self.session.post(self.args.endpoint, files={
            'file_a': open(self.args.file[0], 'rb'),
            'file_b': open(self.args.file[1], 'rb'),
        })

        response.raise_for_status()
        poll_uri = response.json()['result']['uri']

        while True:
            response = self.session.get(poll_uri)
            response.raise_for_status()
            comparison = response.json()['result']

            # Bail out early if --url or --webbrowser specified
            if self.args.url or self.args.webbrowser:
                print(comparison['uri'])

                if self.args.webbrowser:
                    webbrowser.open(comparison['uri'])

                return 0

            if comparison['state'] not in ('queued', 'running'):
                break

            time.sleep(1)

        if comparison['state'] not in ('identical', 'different'):
            print("E: Received state '{}' from server. See {}".format(
                comparison['state'],
                comparison['uri'],
            ), file=sys.stderr)
            return 2

        if comparison['state'] == 'identical':
            return 0

        # Report/save output
        to_save = {x for x in ('html', 'text') if getattr(self.args, x)}

        for x in to_save:
            response = self.session.get(comparison['formats'][x])
            response.raise_for_status()

            with open(getattr(self.args, x), 'w') as f:
                print(response.text, file=f)

        if not to_save:
            response = self.session.get(comparison['formats']['text'])
            response.raise_for_status()
            print(response.content.decode('utf-8'))

        return 1


if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument(
        'file',
        help="files to compare",
        nargs=2,
        default=[],
    )

    parser.add_argument(
        '--endpoint',
        help="specify trydiffoscope API endpoint",
        default='https://try.diffoscope.org/api/v3/comparison',
    )

    parser.add_argument(
        '--text',
        help="write plain text output to given file",
        default=None,
    )

    parser.add_argument(
        '--html',
        help="write HTML report to given file",
        default=None,
    )

    parser.add_argument(
        '-u',
        '--url',
        help="print URL instead of managing results locally",
        action='store_true',
    )

    parser.add_argument(
        '-w',
        '--webbrowser',
        help="open webbrowser to URL instead of managing results "
             "locally (implies -u)",
        action='store_true',
    )

    args = parser.parse_args()

    for x in args.file:
        if not os.path.exists(x):
            parser.error("{}: does not exist".format(x))

    if sys.stdout.encoding != 'UTF-8':
        sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='UTF-8')

    try:
        sys.exit(TryDiffoscope(args).main())
    except KeyboardInterrupt:
        sys.exit(1)
