#!/usr/bin/env python
# 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/.

import os
import sys

sys.path.insert(1, os.path.dirname(sys.path[0]))

from mozharness.base.script import BaseScript
from mozharness.mozilla.bouncer.submitter import BouncerSubmitterMixin
from mozharness.mozilla.buildbot import BuildbotMixin
from mozharness.mozilla.purge import PurgeMixin


class BouncerSubmitter(BaseScript, PurgeMixin, BouncerSubmitterMixin, BuildbotMixin):
    config_options = [
        [["--repo"], {
            "dest": "repo",
            "help": "Specify source repo, e.g. releases/mozilla-beta",
        }],
        [["--revision"], {
            "dest": "revision",
            "help": "Source revision/tag used to fetch shipped-locales",
        }],
        [["--version"], {
            "dest": "version",
            "help": "Current version",
        }],
        [["--previous-version"], {
            "dest": "prev_versions",
            "action": "extend",
            "help": "Previous version(s)",
        }],
        [["--build-number"], {
            "dest": "build_number",
            "help": "Build number of version",
        }],
        [["--bouncer-api-prefix"], {
            "dest": "bouncer-api-prefix",
            "help": "Bouncer admin API URL prefix",
        }],
        [["--credentials-file"], {
            "dest": "credentials_file",
            "help": "File containing Bouncer credentials",
        }],
    ]

    def __init__(self, require_config_file=True):
        BaseScript.__init__(self,
                            config_options=self.config_options,
                            require_config_file=require_config_file,
                            # other stuff
                            all_actions=[
                                'clobber',
                                'download-shipped-locales',
                                'submit',
                            ],
                            default_actions=[
                                'clobber',
                                'download-shipped-locales',
                                'submit',
                            ],
                            config={
                                 'buildbot_json_path': 'buildprops.json'
                            }
                            )
        self.locales = None
        self.credentials = None

    def _pre_config_lock(self, rw_config):
        super(BouncerSubmitter, self)._pre_config_lock(rw_config)

        # override properties from buildbot properties here as defined by taskcluster properties
        self.read_buildbot_config()

        # check if release promotion is true first before overwriting these properties
        if self.buildbot_config["properties"].get("release_promotion"):
            for prop in \
                    ['product', 'version', 'build_number', 'revision',
                     'bouncer_submitter_config', ]:
                if self.buildbot_config["properties"].get(prop):
                    self.info("Overriding %s with %s" %
                              (prop,  self.buildbot_config["properties"].get(prop)))
                    self.config[prop] = self.buildbot_config["properties"].get(prop)
            if self.buildbot_config["properties"].get("partial_versions"):
                self.config["prev_versions"] = \
                    self.buildbot_config["properties"].get("partial_versions").split(", ")

        for opt in ["version", "credentials_file", "bouncer-api-prefix"]:
            if opt not in self.config:
                self.fatal("%s must be specified" % opt)
        if self.need_shipped_locales():
            for opt in ["shipped-locales-url", "repo", "revision"]:
                if opt not in self.config:
                    self.fatal("%s must be specified" % opt)

    def need_shipped_locales(self):
        return any(e.get("add-locales") for e in
                   self.config["products"].values())

    def query_shipped_locales_path(self):
        dirs = self.query_abs_dirs()
        return os.path.join(dirs["abs_work_dir"], "shipped-locales")

    def download_shipped_locales(self):
        if not self.need_shipped_locales():
            self.info("No need to download shipped-locales")
            return

        replace_dict = {"revision": self.config["revision"],
                        "repo": self.config["repo"]}
        url = self.config["shipped-locales-url"] % replace_dict
        dirs = self.query_abs_dirs()
        self.mkdir_p(dirs["abs_work_dir"])
        if not self.download_file(url=url,
                                  file_name=self.query_shipped_locales_path()):
            self.fatal("Unable to fetch shipped-locales from %s" % url)
        # populate the list
        self.load_shipped_locales()

    def load_shipped_locales(self):
        if self.locales:
            return self.locales
        content = self.read_from_file(self.query_shipped_locales_path())
        locales = []
        for line in content.splitlines():
            locale = line.split()[0]
            if locale:
                locales.append(locale)
        self.locales = locales
        return self.locales

    def submit(self):
        subs = {
            "version": self.config["version"]
        }
        if self.config.get("build_number"):
            subs["build_number"] = self.config["build_number"]

        for product, pr_config in sorted(self.config["products"].items()):
            product_name = pr_config["product-name"] % subs
            if self.product_exists(product_name):
                self.warning("Product %s already exists. Skipping..." %
                             product_name)
                continue
            self.info("Adding %s..." % product)
            self.api_add_product(
                product_name=product_name,
                add_locales=pr_config.get("add-locales"),
                ssl_only=pr_config.get("ssl-only"))
            self.info("Adding paths...")
            for platform, pl_config in sorted(pr_config["paths"].items()):
                bouncer_platform = pl_config["bouncer-platform"]
                path = pl_config["path"] % subs
                self.info("%s (%s): %s" % (platform, bouncer_platform, path))
                self.api_add_location(product_name, bouncer_platform, path)

        # Add partial updates
        if "partials" in self.config and self.config.get("prev_versions"):
            self.submit_partials()

    def submit_partials(self):
        subs = {
            "version": self.config["version"]
        }
        if self.config.get("build_number"):
            subs["build_number"] = self.config["build_number"]
        prev_versions = self.config.get("prev_versions")
        for product, part_config in sorted(self.config["partials"].items()):
            product_name_tmpl = part_config["product-name"]
            for prev_version in prev_versions:
                prev_version, prev_build_number = prev_version.split("build")
                subs["prev_version"] = prev_version
                subs["prev_build_number"] = prev_build_number
                product_name = product_name_tmpl % subs
                if self.product_exists(product_name):
                    self.warning("Product %s already exists. Skipping..." %
                                 product_name)
                    continue
                self.info("Adding partial updates for %s" % product_name)
                self.api_add_product(
                    product_name=product_name,
                    add_locales=part_config.get("add-locales"),
                    ssl_only=part_config.get("ssl-only"))
                for platform, pl_config in sorted(part_config["paths"].items()):
                    bouncer_platform = pl_config["bouncer-platform"]
                    path = pl_config["path"] % subs
                    self.info("%s (%s): %s" % (platform, bouncer_platform, path))
                    self.api_add_location(product_name, bouncer_platform, path)


if __name__ == '__main__':
    myScript = BouncerSubmitter()
    myScript.run_and_exit()
