#!/usr/bin/env python

from __future__ import absolute_import, print_function

import unittest
import mozunit
import io
import os
import shutil
import tempfile
import requests
import threading
import time
import re
import mock
import six
from mozgeckoprofiler import view_gecko_profile

if six.PY2:
    # Import for Python 2
    from urllib import unquote
else:
    # Import for Python 3
    from urllib.parse import unquote


def access_profiler_link(file_url, response):
    """Attempts to access the profile in a loop for 5 seconds.

    This is run from a separate thread.
    """
    timeout = 5  # seconds
    start = time.time()

    while time.time() - start < timeout:
        # Poll the server to try and get a response.
        result = requests.get(url=file_url)
        if result.ok:
            # Return the text back in a list.
            response[0] = result.text
            return
        time.sleep(0.1)

    response[0] = "Accessing the profiler link timed out after %s seconds" % timeout


class TestViewGeckoProfile(unittest.TestCase):
    """Tests the opening local profiles in the Firefox Profiler."""

    def setUp(self):
        self.firefox_profiler_url = None
        self.thread = None
        self.response = [None]

    def test_view_gecko_profile(self):

        # Create a temporary fake performance profile.
        temp_dir = tempfile.mkdtemp()
        profile_path = os.path.join(temp_dir, "fakeprofile.json")
        with io.open(profile_path, "w") as f:
            f.write(u"FAKE_PROFILE")

        # Mock the open_new_tab function so that we know when the view_gecko_profile
        # function has done all of its work, and we can assert ressult of the
        # user behavior.
        def mocked_open_new_tab(firefox_profiler_url):
            self.firefox_profiler_url = firefox_profiler_url
            encoded_file_url = firefox_profiler_url.split("/")[-1]
            decoded_file_url = unquote(encoded_file_url)
            # Extract the actual file from the path.
            self.thread = threading.Thread(
                target=access_profiler_link, args=(decoded_file_url, self.response)
            )
            print("firefox_profiler_url %s" % firefox_profiler_url)
            print("encoded_file_url %s" % encoded_file_url)
            print("decoded_file_url %s" % decoded_file_url)
            self.thread.start()

        with mock.patch("webbrowser.open_new_tab", new=mocked_open_new_tab):
            # Run the test
            view_gecko_profile(profile_path)

        self.thread.join()

        # Compare the URLs, but replace the PORT value supplied, as that is dynamic.
        expected_url = (
            "https://profiler.firefox.com/from-url/"
            "http%3A%2F%2F127.0.0.1%3A{PORT}%2Ffakeprofile.json"
        )
        actual_url = re.sub("%3A\d+%2F", "%3A{PORT}%2F", self.firefox_profiler_url)

        self.assertEqual(
            actual_url,
            expected_url,
            "The URL generated was correct for the Firefox Profiler.",
        )
        self.assertEqual(
            self.response[0],
            "FAKE_PROFILE",
            "The response from the serve provided the profile contents.",
        )

        shutil.rmtree(temp_dir)


if __name__ == "__main__":
    mozunit.main()
