# encoding: utf-8
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Author: Trung Do (chin.bimbo@gmail.com)
#
from __future__ import division
from __future__ import unicode_literals

import json
import taskcluster

from pyLibrary import convert
from pyLibrary.debugs.logs import Log
from pyLibrary.dot import wrap
from pyLibrary.env import http
from testlog_etl.transforms import EtlHeadGenerator
from mohg.repos.changesets import Changeset
from mohg.repos.revisions import Revision


def process(source_key, source, destination, resources, please_stop=None):
    """
    This transform will turn a pulse message containing info about a jscov artifact on taskcluster
    into a list of records of line coverages. Each record represents a line.
    :param source_key: The key of the file containing the pulse messages in the source pulse message bucket
    :param source: The source pulse messages, in a batch of (usually) 100
    :param destination: The destination for the transformed data
    :param resources: not used
    :param please_stop: The stop signal to stop the current thread
    :return: The list of keys of files in the destination bucket
    """
    keys = []
    records = []
    etl_header_gen = EtlHeadGenerator(source_key)
    print "Processing " + source_key
    bucket_file_count = -1

    for msg_line_index, msg_line in enumerate(source.read_lines()):
        if please_stop:
            Log.error("Shutdown detected. Stopping job ETL.")

        pulse_record = convert.json2value(msg_line)
        artifact_file_name = pulse_record.artifact.name

        # we're only interested in jscov files, at lease at the moment
        if "jscov" not in artifact_file_name:
            continue

        # create the key for the file in the bucket, and add it to a list to return later
        bucket_file_count += 1
        bucket_key = source_key + "." + unicode(bucket_file_count)
        keys.append(bucket_key)

        # construct the artifact's full url
        taskId = pulse_record.status.taskId
        runId = pulse_record.runId
        full_artifact_path = "https://public-artifacts.taskcluster.net/" + taskId + "/" + unicode(runId) + "/" + artifact_file_name

        # get revision info
        repo = get_revision_info(taskId, resources)

        # fetch the artifact
        response = http.get(full_artifact_path).all_content

        # transform
        json_data = wrap(json.loads(response))
        for source_file_index, obj in enumerate(json_data):
            if please_stop:
                Log.error("Shutdown detected. Stopping job ETL.")

            # get the test name. Just use the test file name at the moment
            # TODO: change this when needed
            test_name = obj.testUrl.split("/")[-1]

            for line_index, line in enumerate(obj.covered):
                _, dest_etl = etl_header_gen.next(pulse_record.etl, source_file_index)

                # reusing dest_etl.id, which should be continuous
                record_key = bucket_key + "." + unicode(dest_etl.id)

                new_line = wrap({
                    "test": {
                        "name": test_name,
                        "url": obj.testUrl
                    },
                    "source": {
                        "file": obj.sourceFile,
                        "covered": line
                    },
                    "etl": dest_etl,
                    "repo": repo
                })

                # file marker
                if line_index == 0:
                    new_line.source.is_file = "true"

                records.append({"id": record_key, "value": new_line})

    destination.extend(records)
    return keys


def get_revision_info(taskId, resources):
    """
    Get the changeset, revision and push info for a given task in TaskCluster
    :param taskId: The taskId of the task
    :param resources: Pass this from the process method
    :return: The repo object containing information about the changeset, revision and push
    """
    queue = taskcluster.Queue()
    task_definition = wrap(queue.task(taskId=taskId))

    # head_repo will look like "https://hg.mozilla.org/try/"
    head_repo = task_definition.payload.env.GECKO_HEAD_REPOSITORY
    branch = head_repo.split("/")[-2]

    revision = task_definition.payload.env.GECKO_HEAD_REV
    rev = Revision(branch={"name": branch}, changeset=Changeset(id=revision))
    repo = resources.hg.get_revision(rev)
    return repo

@@ -461,17 +461,23 @@
 ort wrap
+, Dict
 %0A
-
 from pyL
@@ -2356,24 +2356,155 @@
   # get 
-revis
+the task definition%0A        queue = taskcluster.Queue()%0A        task_definition = wrap(queue.task(taskId=taskId))%0A%0A        # get addit
 ion
+al
  info%0A  
@@ -2530,34 +2530,43 @@
 vision_info(task
-Id
+_definition
 , resources)%0A%0A  
@@ -2561,16 +2561,60 @@
 sources)
+%0A        run = get_run_info(task_definition)
 %0A%0A      
@@ -3759,16 +3759,48 @@
 o%22: repo
+,%0A                    %22run%22: run
 %0A       
@@ -4079,18 +4079,27 @@
 nfo(task
-Id
+_definition
 , resour
@@ -4209,34 +4209,40 @@
 task
-Id: The taskId of the task
+_definition: The task definition
 %0A   
@@ -4396,94 +4396,8 @@
  %22%22%22
-%0A    queue = taskcluster.Queue()%0A    task_definition = wrap(queue.task(taskId=taskId))
 %0A%0A  
@@ -4738,16 +4738,16 @@
 on(rev)%0A
-
     retu
@@ -4754,8 +4754,353 @@
 rn repo%0A
+%0A%0Adef get_run_info(task_definition):%0A    %22%22%22%0A    Get the run object that contains properties that describe the run of this job%0A    :param task_definition: The task definition%0A    :return: The run object%0A    %22%22%22%0A    run = Dict()%0A    run.suite = task_definition.extra.suite.name%0A    run.chunk = task_definition.extra.chunks.current%0A    return run%0A

Add a basic run object