#
# BitBake Toaster Implementation
#
# Copyright (C) 2016        Intel Corporation
#
# SPDX-License-Identifier: GPL-2.0-only
#
# Please run flake8 on this file before sending patches

import os
import re
import logging
import json
import glob
from collections import Counter

from orm.models import Project, ProjectTarget, Build, Layer_Version
from orm.models import LayerVersionDependency, LayerSource, ProjectLayer
from orm.models import Recipe, CustomImageRecipe, CustomImagePackage
from orm.models import Layer, Target, Package, Package_Dependency
from orm.models import ProjectVariable
from bldcontrol.models import BuildRequest, BuildEnvironment
from bldcontrol import bbcontroller

from django.http import HttpResponse, JsonResponse
from django.views.generic import View
from django.urls import reverse
from django.db.models import Q, F
from django.db import Error
from toastergui.templatetags.projecttags import filtered_filesizeformat

# development/debugging support
verbose = 2
def _log(msg):
    if 1 == verbose:
        print(msg)
    elif 2 == verbose:
        f1=open('/tmp/toaster.log', 'a')
        f1.write("|" + msg + "|\n" )
        f1.close()

logger = logging.getLogger("toaster")


def error_response(error):
    return JsonResponse({"error": error})


class XhrBuildRequest(View):

    def get(self, request, *args, **kwargs):
        return HttpResponse()

    @staticmethod
    def cancel_build(br):
        """Cancel a build request"""
        try:
            bbctrl = bbcontroller.BitbakeController(br.environment)
            bbctrl.forceShutDown()
        except:
            # We catch a bunch of exceptions here because
            # this is where the server has not had time to start up
            # and the build request or build is in transit between
            # processes.
            # We can safely just set the build as cancelled
            # already as it never got started
            build = br.build
            build.outcome = Build.CANCELLED
            build.save()

        # We now hand over to the buildinfohelper to update the
        # build state once we've finished cancelling
        br.state = BuildRequest.REQ_CANCELLING
        br.save()

    def post(self, request, *args, **kwargs):
        """
          Build control

          Entry point: /xhr_buildrequest/<project_id>
          Method: POST

          Args:
              id: id of build to change
              buildCancel = build_request_id ...
              buildDelete = id ...
              targets = recipe_name ...

          Returns:
              {"error": "ok"}
            or
              {"error": <error message>}
        """

        project = Project.objects.get(pk=kwargs['pid'])

        if 'buildCancel' in request.POST:
            for i in request.POST['buildCancel'].strip().split(" "):
                try:
                    br = BuildRequest.objects.get(project=project, pk=i)
                    self.cancel_build(br)
                except BuildRequest.DoesNotExist:
                    return error_response('No such build request id %s' % i)

            return error_response('ok')

        if 'buildDelete' in request.POST:
            for i in request.POST['buildDelete'].strip().split(" "):
                try:
                    BuildRequest.objects.select_for_update().get(
                        project=project,
                        pk=i,
                        state__lte=BuildRequest.REQ_DELETED).delete()

                except BuildRequest.DoesNotExist:
                    pass
            return error_response("ok")

        if 'targets' in request.POST:
            ProjectTarget.objects.filter(project=project).delete()
            s = str(request.POST['targets'])
            for t in re.sub(r'[;%|"]', '', s).split(" "):
                if ":" in t:
                    target, task = t.split(":")
                else:
                    target = t
                    task = ""
                ProjectTarget.objects.create(project=project,
                                             target=target,
                                             task=task)
            project.schedule_build()

            return error_response('ok')

        response = HttpResponse()
        response.status_code = 500
        return response


class XhrProjectUpdate(View):

    def get(self, request, *args, **kwargs):
        return HttpResponse()

    def post(self, request, *args, **kwargs):
        """
          Project Update

          Entry point: /xhr_projectupdate/<project_id>
          Method: POST

          Args:
              pid: pid of project to update

          Returns:
              {"error": "ok"}
            or
              {"error": <error message>}
        """

        project = Project.objects.get(pk=kwargs['pid'])
        logger.debug("ProjectUpdateCallback:project.pk=%d,project.builddir=%s" % (project.pk,project.builddir))

        if 'do_update' in request.POST:

            # Extract any default image recipe
            if 'default_image' in request.POST:
                project.set_variable(Project.PROJECT_SPECIFIC_DEFAULTIMAGE,str(request.POST['default_image']))
            else:
                project.set_variable(Project.PROJECT_SPECIFIC_DEFAULTIMAGE,'')

            logger.debug("ProjectUpdateCallback:Chain to the build request")

            # Chain to the build request
            xhrBuildRequest = XhrBuildRequest()
            return xhrBuildRequest.post(request, *args, **kwargs)

        logger.warning("ERROR:XhrProjectUpdate")
        response = HttpResponse()
        response.status_code = 500
        return response

class XhrSetDefaultImageUrl(View):

    def get(self, request, *args, **kwargs):
        return HttpResponse()

    def post(self, request, *args, **kwargs):
        """
          Project Update

          Entry point: /xhr_setdefaultimage/<project_id>
          Method: POST

          Args:
              pid: pid of project to update default image

          Returns:
              {"error": "ok"}
            or
              {"error": <error message>}
        """

        project = Project.objects.get(pk=kwargs['pid'])
        logger.debug("XhrSetDefaultImageUrl:project.pk=%d" % (project.pk))

        # set any default image recipe
        if 'targets' in request.POST:
            default_target = str(request.POST['targets'])
            project.set_variable(Project.PROJECT_SPECIFIC_DEFAULTIMAGE,default_target)
            logger.debug("XhrSetDefaultImageUrl,project.pk=%d,project.builddir=%s" % (project.pk,project.builddir))
            return error_response('ok')

        logger.warning("ERROR:XhrSetDefaultImageUrl")
        response = HttpResponse()
        response.status_code = 500
        return response


#
# Layer Management
#
# Rules for 'local_source_dir' layers
#  * Layers must have a unique name in the Layers table
#  * A 'local_source_dir' layer is supposed to be shared
#    by all projects that use it, so that it can have the
#    same logical name
#  * Each project that uses a layer will have its own
#    LayerVersion and Project Layer for it
#  * During the Project delete process, when the last
#    LayerVersion for a 'local_source_dir' layer is deleted
#    then the Layer record is deleted to remove orphans
#

def scan_layer_content(layer,layer_version):
    # if this is a local layer directory, we can immediately scan its content
    if os.path.isdir(layer.local_source_dir):
        try:
            # recipes-*/*/*.bb
            recipes_list = glob.glob(os.path.join(layer.local_source_dir, 'recipes-*/*/*.bb'))
            for recipe in recipes_list:
                for recipe in recipes_list.split('\n'):
                    recipe_path = recipe[recipe.rfind('recipes-'):]
                    recipe_name = recipe[recipe.rfind('/')+1:].replace('.bb','')
                    recipe_ver = recipe_name.rfind('_')
                    if recipe_ver > 0:
                        recipe_name = recipe_name[0:recipe_ver]
                    if recipe_name:
                        ro, created = Recipe.objects.get_or_create(
                            layer_version=layer_version,
                            name=recipe_name
                        )
                        if created:
                            ro.file_path = recipe_path
                            ro.summary = 'Recipe %s from layer %s' % (recipe_name,layer.name)
                            ro.description = ro.summary
                        ro.save()

        except Exception as e:
            logger.warning("ERROR:scan_layer_content: %s" % e)
    else:
        logger.warning("ERROR: wrong path given")
        raise KeyError("local_source_dir")

class XhrLayer(View):
    """ Delete, Get, Add and Update Layer information

        Methods: GET POST DELETE PUT
    """

    def get(self, request, *args, **kwargs):
        """
        Get layer information

        Method: GET
        Entry point: /xhr_layer/<project id>/<layerversion_id>
        """

        try:
            layer_version = Layer_Version.objects.get(
                pk=kwargs['layerversion_id'])

            project = Project.objects.get(pk=kwargs['pid'])

            project_layers = ProjectLayer.objects.filter(
                project=project).values_list("layercommit_id",
                                             flat=True)

            ret = {
                'error': 'ok',
                'id': layer_version.pk,
                'name': layer_version.layer.name,
                'layerdetailurl':
                layer_version.get_detailspage_url(project.pk),
                'vcs_ref': layer_version.get_vcs_reference(),
                'vcs_url': layer_version.layer.vcs_url,
                'local_source_dir': layer_version.layer.local_source_dir,
                'layerdeps': {
                    "list": [
                        {
                            "id": dep.id,
                            "name": dep.layer.name,
                            "layerdetailurl":
                            dep.get_detailspage_url(project.pk),
                            "vcs_url": dep.layer.vcs_url,
                            "vcs_reference": dep.get_vcs_reference()
                        }
                        for dep in layer_version.get_alldeps(project.id)]
                },
                'projectlayers': list(project_layers)
            }

            return JsonResponse(ret)
        except Layer_Version.DoesNotExist:
            error_response("No such layer")

    def post(self, request, *args, **kwargs):
        """
          Update a layer

          Method: POST
          Entry point: /xhr_layer/<layerversion_id>

          Args:
              vcs_url, dirpath, commit, up_branch, summary, description,
              local_source_dir

              add_dep = append a layerversion_id as a dependency
              rm_dep = remove a layerversion_id as a depedency
          Returns:
              {"error": "ok"}
            or
              {"error": <error message>}
        """

        try:
            # We currently only allow Imported layers to be edited
            layer_version = Layer_Version.objects.get(
                id=kwargs['layerversion_id'],
                project=kwargs['pid'],
                layer_source=LayerSource.TYPE_IMPORTED)

        except Layer_Version.DoesNotExist:
            return error_response("Cannot find imported layer to update")

        if "vcs_url" in request.POST:
            layer_version.layer.vcs_url = request.POST["vcs_url"]
        if "dirpath" in request.POST:
            layer_version.dirpath = request.POST["dirpath"]
        if "commit" in request.POST:
            layer_version.commit = request.POST["commit"]
            layer_version.branch = request.POST["commit"]
        if "summary" in request.POST:
            layer_version.layer.summary = request.POST["summary"]
        if "description" in request.POST:
            layer_version.layer.description = request.POST["description"]
        if "local_source_dir" in request.POST:
            layer_version.layer.local_source_dir = \
                request.POST["local_source_dir"]

        if "add_dep" in request.POST:
            lvd = LayerVersionDependency(
                layer_version=layer_version,
                depends_on_id=request.POST["add_dep"])
            lvd.save()

        if "rm_dep" in request.POST:
            rm_dep = LayerVersionDependency.objects.get(
                layer_version=layer_version,
                depends_on_id=request.POST["rm_dep"])
            rm_dep.delete()

        try:
            layer_version.layer.save()
            layer_version.save()
        except Exception as e:
            return error_response("Could not update layer version entry: %s"
                                  % e)

        return error_response("ok")

    def put(self, request, *args, **kwargs):
        """ Add a new layer

        Method: PUT
        Entry point: /xhr_layer/<project id>/
        Args:
            project_id, name,
            [vcs_url, dir_path, git_ref], [local_source_dir], [layer_deps
            (csv)]

        """

        try:
            project = Project.objects.get(pk=kwargs['pid'])

            layer_data = json.loads(request.body.decode('utf-8'))

            # We require a unique layer name as otherwise the lists of layers
            # becomes very confusing
            existing_layers = \
                project.get_all_compatible_layer_versions().values_list(
                    "layer__name",
                    flat=True)

            add_to_project = False
            layer_deps_added = []
            if 'add_to_project' in layer_data:
                add_to_project = True

            if layer_data['name'] in existing_layers:
                return JsonResponse({"error": "layer-name-exists"})

            if ('local_source_dir' in layer_data):
                # Local layer can be shared across projects. They have no 'release'
                # and are not included in get_all_compatible_layer_versions() above
                layer,created = Layer.objects.get_or_create(name=layer_data['name'])
                _log("Local Layer created=%s" % created)
            else:
                layer = Layer.objects.create(name=layer_data['name'])

            layer_version = Layer_Version.objects.create(
                layer=layer,
                project=project,
                layer_source=LayerSource.TYPE_IMPORTED)

            # Local layer
            if ('local_source_dir' in layer_data): ### and layer.local_source_dir:
                layer.local_source_dir = layer_data['local_source_dir']
            # git layer
            elif 'vcs_url' in layer_data:
                layer.vcs_url = layer_data['vcs_url']
                layer_version.dirpath = layer_data['dir_path']
                layer_version.commit = layer_data['git_ref']
                layer_version.branch = layer_data['git_ref']

            layer.save()
            layer_version.save()

            if add_to_project:
                ProjectLayer.objects.get_or_create(
                    layercommit=layer_version, project=project)

            # Add the layer dependencies
            if 'layer_deps' in layer_data:
                for layer_dep_id in layer_data['layer_deps'].split(","):
                    layer_dep = Layer_Version.objects.get(pk=layer_dep_id)
                    LayerVersionDependency.objects.get_or_create(
                        layer_version=layer_version, depends_on=layer_dep)

                    # Add layer deps to the project if specified
                    if add_to_project:
                        created, pl = ProjectLayer.objects.get_or_create(
                            layercommit=layer_dep, project=project)
                        layer_deps_added.append(
                            {'name': layer_dep.layer.name,
                             'layerdetailurl':
                             layer_dep.get_detailspage_url(project.pk)})

            # Only scan_layer_content if layer is local
            if layer_data.get('local_source_dir', None):
                # Scan the layer's content and update components
                scan_layer_content(layer,layer_version)

        except Layer_Version.DoesNotExist:
            return error_response("layer-dep-not-found")
        except Project.DoesNotExist:
            return error_response("project-not-found")
        except KeyError as e:
            _log("KeyError: %s" % e)
            return error_response(f"incorrect-parameters")

        return JsonResponse({'error': "ok",
                             'imported_layer': {
                                 'name': layer.name,
                                 'layerdetailurl':
                                 layer_version.get_detailspage_url()},
                             'deps_added': layer_deps_added})

    def delete(self, request, *args, **kwargs):
        """ Delete an imported layer

        Method: DELETE
        Entry point: /xhr_layer/<projed id>/<layerversion_id>

        """
        try:
            # We currently only allow Imported layers to be deleted
            layer_version = Layer_Version.objects.get(
                id=kwargs['layerversion_id'],
                project=kwargs['pid'],
                layer_source=LayerSource.TYPE_IMPORTED)
        except Layer_Version.DoesNotExist:
            return error_response("Cannot find imported layer to delete")

        try:
            ProjectLayer.objects.get(project=kwargs['pid'],
                                     layercommit=layer_version).delete()
        except ProjectLayer.DoesNotExist:
            pass

        layer_version.layer.delete()
        layer_version.delete()

        return JsonResponse({
            "error": "ok",
            "gotoUrl": reverse('projectlayers', args=(kwargs['pid'],))
        })


class XhrCustomRecipe(View):
    """ Create a custom image recipe """

    def post(self, request, *args, **kwargs):
        """
        Custom image recipe REST API

        Entry point: /xhr_customrecipe/
        Method: POST

        Args:
            name: name of custom recipe to create
            project: target project id of orm.models.Project
            base: base recipe id of orm.models.Recipe

        Returns:
            {"error": "ok",
             "url": <url of the created recipe>}
            or
            {"error": <error message>}
        """
        # check if request has all required parameters
        for param in ('name', 'project', 'base'):
            if param not in request.POST:
                return error_response("Missing parameter '%s'" % param)

        # get project and baserecipe objects
        params = {}
        for name, model in [("project", Project),
                            ("base", Recipe)]:
            value = request.POST[name]
            try:
                params[name] = model.objects.get(id=value)
            except model.DoesNotExist:
                return error_response("Invalid %s id %s" % (name, value))

        # create custom recipe
        try:

            # Only allowed chars in name are a-z, 0-9 and -
            if re.search(r'[^a-z|0-9|-]', request.POST["name"]):
                return error_response("invalid-name")

            custom_images = CustomImageRecipe.objects.all()

            # Are there any recipes with this name already in our project?
            existing_image_recipes_in_project = custom_images.filter(
                name=request.POST["name"], project=params["project"])

            if existing_image_recipes_in_project.count() > 0:
                return error_response("image-already-exists")

            # Are there any recipes with this name which aren't custom
            # image recipes?
            custom_image_ids = custom_images.values_list('id', flat=True)
            existing_non_image_recipes = Recipe.objects.filter(
                Q(name=request.POST["name"]) & ~Q(pk__in=custom_image_ids)
            )

            if existing_non_image_recipes.count() > 0:
                return error_response("recipe-already-exists")

            # create layer 'Custom layer' and verion if needed
            layer, l_created = Layer.objects.get_or_create(
                name=CustomImageRecipe.LAYER_NAME,
                summary="Layer for custom recipes")

            if l_created:
                layer.local_source_dir = "toaster_created_layer"
                layer.save()

            # Check if we have a layer version already
            # We don't use get_or_create here because the dirpath will change
            # and is a required field
            lver = Layer_Version.objects.filter(Q(project=params['project']) &
                                                Q(layer=layer) &
                                                Q(build=None)).last()
            if lver is None:
                lver, lv_created = Layer_Version.objects.get_or_create(
                    project=params['project'],
                    layer=layer,
                    layer_source=LayerSource.TYPE_LOCAL,
                    dirpath="toaster_created_layer")

            # Add a dependency on our layer to the base recipe's layer
            LayerVersionDependency.objects.get_or_create(
                layer_version=lver,
                depends_on=params["base"].layer_version)

            # Add it to our current project if needed
            ProjectLayer.objects.get_or_create(project=params['project'],
                                               layercommit=lver,
                                               optional=False)

            # Create the actual recipe
            recipe, r_created = CustomImageRecipe.objects.get_or_create(
                name=request.POST["name"],
                base_recipe=params["base"],
                project=params["project"],
                layer_version=lver,
                is_image=True)

            # If we created the object then setup these fields. They may get
            # overwritten later on and cause the get_or_create to create a
            # duplicate if they've changed.
            if r_created:
                recipe.file_path = request.POST["name"]
                recipe.license = "MIT"
                recipe.version = "0.1"
                recipe.save()

        except Error as err:
            return error_response("Can't create custom recipe: %s" % err)

        # Find the package list from the last build of this recipe/target
        target = Target.objects.filter(Q(build__outcome=Build.SUCCEEDED) &
                                       Q(build__project=params['project']) &
                                       (Q(target=params['base'].name) |
                                        Q(target=recipe.name))).last()
        if target:
            # Copy in every package
            # We don't want these packages to be linked to anything because
            # that underlying data may change e.g. delete a build
            for tpackage in target.target_installed_package_set.all():
                try:
                    built_package = tpackage.package
                    # The package had no recipe information so is a ghost
                    # package skip it
                    if built_package.recipe is None:
                        continue

                    config_package = CustomImagePackage.objects.get(
                        name=built_package.name)

                    recipe.includes_set.add(config_package)
                except Exception as e:
                    logger.warning("Error adding package %s %s" %
                                   (tpackage.package.name, e))
                    pass

        # pre-create layer directory structure, so that other builds
        # are not blocked by this new recipe dependecy
        # NOTE: this is parallel code to 'localhostbecontroller.py'
        be = BuildEnvironment.objects.all()[0]
        layerpath = os.path.join(be.builddir,
                                 CustomImageRecipe.LAYER_NAME)
        for name in ("conf", "recipes"):
            path = os.path.join(layerpath, name)
            if not os.path.isdir(path):
                os.makedirs(path)
        # pre-create layer.conf
        config = os.path.join(layerpath, "conf", "layer.conf")
        if not os.path.isfile(config):
            with open(config, "w") as conf:
                conf.write('BBPATH .= ":${LAYERDIR}"\nBBFILES += "${LAYERDIR}/recipes/*.bb"\n')
        # pre-create new image's recipe file
        recipe_path = os.path.join(layerpath, "recipes", "%s.bb" %
                                   recipe.name)
        with open(recipe_path, "w") as recipef:
            content = recipe.generate_recipe_file_contents()
            if not content:
                # Delete this incomplete image recipe object
                recipe.delete()
                return error_response("recipe-parent-not-exist")
            else:
                recipef.write(recipe.generate_recipe_file_contents())

        return JsonResponse(
            {"error": "ok",
             "packages": recipe.get_all_packages().count(),
             "url": reverse('customrecipe', args=(params['project'].pk,
                                                  recipe.id))})


class XhrCustomRecipeId(View):
    """
    Set of ReST API processors working with recipe id.

    Entry point: /xhr_customrecipe/<recipe_id>

    Methods:
        GET - Get details of custom image recipe
        DELETE - Delete custom image recipe

    Returns:
        GET:
        {"error": "ok",
        "info": dictionary of field name -> value pairs
        of the CustomImageRecipe model}
        DELETE:
        {"error": "ok"}
          or
        {"error": <error message>}
    """
    @staticmethod
    def _get_ci_recipe(recipe_id):
        """ Get Custom Image recipe or return an error response"""
        try:
            custom_recipe = \
                CustomImageRecipe.objects.get(pk=recipe_id)
            return custom_recipe, None

        except CustomImageRecipe.DoesNotExist:
            return None, error_response("Custom recipe with id=%s "
                                        "not found" % recipe_id)

    def get(self, request, *args, **kwargs):
        custom_recipe, error = self._get_ci_recipe(kwargs['recipe_id'])
        if error:
            return error

        if request.method == 'GET':
            info = {"id": custom_recipe.id,
                    "name": custom_recipe.name,
                    "base_recipe_id": custom_recipe.base_recipe.id,
                    "project_id": custom_recipe.project.id}

            return JsonResponse({"error": "ok", "info": info})

    def delete(self, request, *args, **kwargs):
        custom_recipe, error = self._get_ci_recipe(kwargs['recipe_id'])
        if error:
            return error

        project = custom_recipe.project

        custom_recipe.delete()
        return JsonResponse({"error": "ok",
                             "gotoUrl": reverse("projectcustomimages",
                                                args=(project.pk,))})


class XhrCustomRecipePackages(View):
    """
    ReST API to add/remove packages to/from custom recipe.

    Entry point: /xhr_customrecipe/<recipe_id>/packages/<package_id>
    Methods:
         PUT - Add package to the recipe
         DELETE - Delete package from the recipe
         GET - Get package information

     Returns:
         {"error": "ok"}
          or
          {"error": <error message>}
    """
    @staticmethod
    def _get_package(package_id):
        try:
            package = CustomImagePackage.objects.get(pk=package_id)
            return package, None
        except Package.DoesNotExist:
            return None, error_response("Package with id=%s "
                                        "not found" % package_id)

    def _traverse_dependents(self, next_package_id,
                             rev_deps, all_current_packages, tree_level=0):
        """
        Recurse through reverse dependency tree for next_package_id.
        Limit the reverse dependency search to packages not already scanned,
        that is, not already in rev_deps.
        Limit the scan to a depth (tree_level) not exceeding the count of
        all packages in the custom image, and if that depth is exceeded
        return False, pop out of the recursion, and write a warning
        to the log, but this is unlikely, suggesting a dependency loop
        not caught by bitbake.
        On return, the input/output arg rev_deps is appended with queryset
        dictionary elements, annotated for use in the customimage template.
        The list has unsorted, but unique elements.
        """
        max_dependency_tree_depth = all_current_packages.count()
        if tree_level >= max_dependency_tree_depth:
            logger.warning(
                "The number of reverse dependencies "
                "for this package exceeds " + max_dependency_tree_depth +
                " and the remaining reverse dependencies will not be removed")
            return True

        package = CustomImagePackage.objects.get(id=next_package_id)
        dependents = \
            package.package_dependencies_target.annotate(
                name=F('package__name'),
                pk=F('package__pk'),
                size=F('package__size'),
            ).values("name", "pk", "size").exclude(
                ~Q(pk__in=all_current_packages)
            )

        for pkg in dependents:
            if pkg in rev_deps:
                # already seen, skip dependent search
                continue

            rev_deps.append(pkg)
            if (self._traverse_dependents(pkg["pk"], rev_deps,
                                          all_current_packages,
                                          tree_level+1)):
                return True

        return False

    def _get_all_dependents(self, package_id, all_current_packages):
        """
        Returns sorted list of recursive reverse dependencies for package_id,
        as a list of dictionary items, by recursing through dependency
        relationships.
        """
        rev_deps = []
        self._traverse_dependents(package_id, rev_deps, all_current_packages)
        rev_deps = sorted(rev_deps, key=lambda x: x["name"])
        return rev_deps

    def get(self, request, *args, **kwargs):
        recipe, error = XhrCustomRecipeId._get_ci_recipe(
            kwargs['recipe_id'])
        if error:
            return error

        # If no package_id then list all the current packages
        if not kwargs['package_id']:
            total_size = 0
            packages = recipe.get_all_packages().values("id",
                                                        "name",
                                                        "version",
                                                        "size")
            for package in packages:
                package['size_formatted'] = \
                    filtered_filesizeformat(package['size'])
                total_size += package['size']

            return JsonResponse({"error": "ok",
                                 "packages": list(packages),
                                 "total": len(packages),
                                 "total_size": total_size,
                                 "total_size_formatted":
                                 filtered_filesizeformat(total_size)})
        else:
            package, error = XhrCustomRecipePackages._get_package(
                kwargs['package_id'])
            if error:
                return error

            all_current_packages = recipe.get_all_packages()

            # Dependencies for package which aren't satisfied by the
            # current packages in the custom image recipe
            deps = package.package_dependencies_source.for_target_or_none(
                recipe.name)['packages'].annotate(
                name=F('depends_on__name'),
                pk=F('depends_on__pk'),
                size=F('depends_on__size'),
                ).values("name", "pk", "size").filter(
                # There are two depends types we don't know why
                (Q(dep_type=Package_Dependency.TYPE_TRDEPENDS) |
                 Q(dep_type=Package_Dependency.TYPE_RDEPENDS)) &
                ~Q(pk__in=all_current_packages)
                )

            # Reverse dependencies which are needed by packages that are
            # in the image. Recursive search providing all dependents,
            # not just immediate dependents.
            reverse_deps = self._get_all_dependents(kwargs['package_id'],
                                                    all_current_packages)
            total_size_deps = 0
            total_size_reverse_deps = 0

            for dep in deps:
                dep['size_formatted'] = \
                    filtered_filesizeformat(dep['size'])
                total_size_deps += dep['size']

            for dep in reverse_deps:
                dep['size_formatted'] = \
                    filtered_filesizeformat(dep['size'])
                total_size_reverse_deps += dep['size']

            return JsonResponse(
                {"error": "ok",
                 "id": package.pk,
                 "name": package.name,
                 "version": package.version,
                 "unsatisfied_dependencies": list(deps),
                 "unsatisfied_dependencies_size": total_size_deps,
                 "unsatisfied_dependencies_size_formatted":
                 filtered_filesizeformat(total_size_deps),
                 "reverse_dependencies": list(reverse_deps),
                 "reverse_dependencies_size": total_size_reverse_deps,
                 "reverse_dependencies_size_formatted":
                 filtered_filesizeformat(total_size_reverse_deps)})

    def put(self, request, *args, **kwargs):
        recipe, error = XhrCustomRecipeId._get_ci_recipe(kwargs['recipe_id'])
        package, error = self._get_package(kwargs['package_id'])
        if error:
            return error

        included_packages = recipe.includes_set.values_list('pk',
                                                            flat=True)

        # If we're adding back a package which used to be included in this
        # image all we need to do is remove it from the excludes
        if package.pk in included_packages:
            try:
                recipe.excludes_set.remove(package)
                return {"error": "ok"}
            except Package.DoesNotExist:
                return error_response("Package %s not found in excludes"
                                      " but was in included list" %
                                      package.name)
        else:
            recipe.appends_set.add(package)
            # Make sure that package is not in the excludes set
            try:
                recipe.excludes_set.remove(package)
            except:
                pass

        # Add the dependencies we think will be added to the recipe
        # as a result of appending this package.
        # TODO this should recurse down the entire deps tree
        for dep in package.package_dependencies_source.all_depends():
            try:
                cust_package = CustomImagePackage.objects.get(
                    name=dep.depends_on.name)

                recipe.includes_set.add(cust_package)
                try:
                    # When adding the pre-requisite package, make
                    # sure it's not in the excluded list from a
                    # prior removal.
                    recipe.excludes_set.remove(cust_package)
                except package.DoesNotExist:
                    # Don't care if the package had never been excluded
                    pass
            except:
                logger.warning("Could not add package's suggested"
                               "dependencies to the list")
        return JsonResponse({"error": "ok"})

    def delete(self, request, *args, **kwargs):
        recipe, error = XhrCustomRecipeId._get_ci_recipe(kwargs['recipe_id'])
        package, error = self._get_package(kwargs['package_id'])
        if error:
            return error

        try:
            included_packages = recipe.includes_set.values_list('pk',
                                                                flat=True)
            # If we're deleting a package which is included we need to
            # Add it to the excludes list.
            if package.pk in included_packages:
                recipe.excludes_set.add(package)
            else:
                recipe.appends_set.remove(package)

            # remove dependencies as well
            all_current_packages = recipe.get_all_packages()

            reverse_deps_dictlist = self._get_all_dependents(
                package.pk,
                all_current_packages)

            ids = [entry['pk'] for entry in reverse_deps_dictlist]
            reverse_deps = CustomImagePackage.objects.filter(id__in=ids)
            for r in reverse_deps:
                try:
                    if r.id in included_packages:
                        recipe.excludes_set.add(r)
                    else:
                        recipe.appends_set.remove(r)
                except:
                    pass

            return JsonResponse({"error": "ok"})
        except CustomImageRecipe.DoesNotExist:
            return error_response("Tried to remove package that wasn't"
                                  " present")


class XhrProject(View):
    """ Create, delete or edit a project

    Entry point: /xhr_project/<project_id>
    """
    def post(self, request, *args, **kwargs):
        """
          Edit project control

          Args:
              layerAdd = layer_version_id layer_version_id ...
              layerDel = layer_version_id layer_version_id ...
              projectName = new_project_name
              machineName = new_machine_name

          Returns:
              {"error": "ok"}
            or
              {"error": <error message>}
        """
        try:
            prj = Project.objects.get(pk=kwargs['project_id'])
        except Project.DoesNotExist:
            return error_response("No such project")

        # Add layers
        if 'layerAdd' in request.POST and len(request.POST['layerAdd']) > 0:
            for layer_version_id in request.POST['layerAdd'].split(','):
                try:
                    lv = Layer_Version.objects.get(pk=int(layer_version_id))
                    ProjectLayer.objects.get_or_create(project=prj,
                                                       layercommit=lv)
                except Layer_Version.DoesNotExist:
                    return error_response("Layer version %s asked to add "
                                          "doesn't exist" % layer_version_id)

        # Remove layers
        if 'layerDel' in request.POST and len(request.POST['layerDel']) > 0:
            layer_version_ids = request.POST['layerDel'].split(',')
            ProjectLayer.objects.filter(
                project=prj,
                layercommit_id__in=layer_version_ids).delete()

        # Project name change
        if 'projectName' in request.POST:
            prj.name = request.POST['projectName']
            prj.save()

        # Machine name change
        if 'machineName' in request.POST:
            machinevar = prj.projectvariable_set.get(name="MACHINE")
            machinevar.value = request.POST['machineName']
            machinevar.save()

        # Distro name change
        if 'distroName' in request.POST:
            distrovar = prj.projectvariable_set.get(name="DISTRO")
            distrovar.value = request.POST['distroName']
            distrovar.save()

        return JsonResponse({"error": "ok"})

    def get(self, request, *args, **kwargs):
        """
        Returns:
            json object representing the current project
        or:
            {"error": <error message>}
        """

        try:
            project = Project.objects.get(pk=kwargs['project_id'])
        except Project.DoesNotExist:
            return error_response("Project %s does not exist" %
                                  kwargs['project_id'])

        # Create the frequently built targets list

        freqtargets = Counter(Target.objects.filter(
            Q(build__project=project),
            ~Q(build__outcome=Build.IN_PROGRESS)
        ).order_by("target").values_list("target", flat=True))

        freqtargets = freqtargets.most_common(5)

        # We now have the targets in order of frequency but if there are two
        # with the same frequency then we need to make sure those are in
        # alphabetical order without losing the frequency ordering

        tmp = []
        switch = None
        for i, freqtartget in enumerate(freqtargets):
            target, count = freqtartget
            try:
                target_next, count_next = freqtargets[i+1]
                if count == count_next and target > target_next:
                    switch = target
                    continue
            except IndexError:
                pass

            tmp.append(target)

            if switch:
                tmp.append(switch)
                switch = None

        freqtargets = tmp

        layers = []
        for layer in project.projectlayer_set.all():
            layers.append({
                "id": layer.layercommit.pk,
                "name": layer.layercommit.layer.name,
                "vcs_url": layer.layercommit.layer.vcs_url,
                "local_source_dir": layer.layercommit.layer.local_source_dir,
                "vcs_reference": layer.layercommit.get_vcs_reference(),
                "url": layer.layercommit.layer.layer_index_url,
                "layerdetailurl": layer.layercommit.get_detailspage_url(
                    project.pk),
                "xhrLayerUrl": reverse("xhr_layer",
                                       args=(project.pk,
                                             layer.layercommit.pk)),
                "layersource": layer.layercommit.layer_source
            })

        data = {
            "name": project.name,
            "layers": layers,
            "freqtargets": freqtargets,
        }

        if project.release is not None:
            data['release'] = {
                "id": project.release.pk,
                "name": project.release.name,
                "description": project.release.description
            }

        try:
            data["machine"] = {"name":
                               project.projectvariable_set.get(
                                   name="MACHINE").value}
        except ProjectVariable.DoesNotExist:
            data["machine"] = None
        try:
            data["distro"] = {"name":
                               project.projectvariable_set.get(
                                   name="DISTRO").value}
        except ProjectVariable.DoesNotExist:
            data["distro"] = None

        data['error'] = "ok"

        return JsonResponse(data)

    def put(self, request, *args, **kwargs):
        # TODO create new project api
        return HttpResponse()

    def delete(self, request, *args, **kwargs):
        """Delete a project. Cancels any builds in progress"""
        try:
            project = Project.objects.get(pk=kwargs['project_id'])
            # Cancel any builds in progress
            for br in BuildRequest.objects.filter(
                    project=project,
                    state=BuildRequest.REQ_INPROGRESS):
                XhrBuildRequest.cancel_build(br)

            # gather potential orphaned local layers attached to this project
            project_local_layer_list = []
            for pl in ProjectLayer.objects.filter(project=project):
                if pl.layercommit.layer_source == LayerSource.TYPE_IMPORTED:
                    project_local_layer_list.append(pl.layercommit.layer)

            # deep delete the project and its dependencies
            project.delete()

            # delete any local layers now orphaned
            _log("LAYER_ORPHAN_CHECK:Check for orphaned layers")
            for layer in project_local_layer_list:
                layer_refs = Layer_Version.objects.filter(layer=layer)
                _log("LAYER_ORPHAN_CHECK:Ref Count for '%s' = %d" % (layer.name,len(layer_refs)))
                if 0 == len(layer_refs):
                    _log("LAYER_ORPHAN_CHECK:DELETE orpahned '%s'" % (layer.name))
                    Layer.objects.filter(pk=layer.id).delete()

        except Project.DoesNotExist:
            return error_response("Project %s does not exist" %
                                  kwargs['project_id'])

        return JsonResponse({
            "error": "ok",
            "gotoUrl": reverse("all-projects", args=[])
        })


class XhrBuild(View):
    """ Delete a build object

    Entry point: /xhr_build/<build_id>
    """
    def delete(self, request, *args, **kwargs):
        """
          Delete build data

          Args:
              build_id = build_id

          Returns:
              {"error": "ok"}
            or
              {"error": <error message>}
        """
        try:
            build = Build.objects.get(pk=kwargs['build_id'])
            project = build.project
            build.delete()
        except Build.DoesNotExist:
            return error_response("Build %s does not exist" %
                                  kwargs['build_id'])
        return JsonResponse({
            "error": "ok",
            "gotoUrl": reverse("projectbuilds", args=(project.pk,))
        })
