# Copyright (C) 2018-2019 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from __future__ import unicode_literals

import logging

from django.db import models
from ews.config import ERR_UNEXPECTED, SUCCESS
from ews.models.buildbotinstance import BuildbotInstance
from ews.models.patch import Patch
import ews.common.util as util

_log = logging.getLogger(__name__)


class Build(models.Model):
    patch = models.ForeignKey(Patch, on_delete=models.CASCADE, db_constraint=False)
    uid = models.TextField(primary_key=True)
    builder_id = models.IntegerField()
    builder_name = models.TextField()
    builder_display_name = models.TextField()
    number = models.IntegerField()
    result = models.IntegerField(null=True, blank=True)
    state_string = models.TextField()
    started_at = models.IntegerField(null=True, blank=True)
    complete_at = models.IntegerField(null=True, blank=True)
    retried = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(self.uid)

    @classmethod
    def save_build(cls, patch_id, hostname, build_id, builder_id, builder_name, builder_display_name, number, result, state_string, started_at, complete_at=None):
        if not Build.is_valid_result(patch_id, build_id, builder_id, number, result, state_string, started_at, complete_at):
            return ERR_UNEXPECTED

        if state_string is None:
            state_string = ''

        uid = BuildbotInstance.get_uid(hostname, build_id)
        build = Build.get_existing_build(uid)
        if build:
            # If the build data is already present in database, update it, e.g.: build complete event.
            return Build.update_build(build, patch_id, uid, builder_id, builder_name, builder_display_name, number, result, state_string, started_at, complete_at)

        if not Patch.is_existing_patch_id(patch_id):
            Patch.save_patch(patch_id)
            _log.info('Received result for unknown patch. Saved patch {} to database'.format(patch_id))

        # Save the new build data, e.g.: build start event.
        Build(patch_id, uid, builder_id, builder_name, builder_display_name, number, result, state_string, started_at, complete_at).save()
        _log.info('Saved build {} in database for patch_id: {}'.format(uid, patch_id))
        return SUCCESS

    @classmethod
    def update_build(cls, build, patch_id, uid, builder_id, builder_name, builder_display_name, number, result, state_string, started_at, complete_at):
        if build.patch_id != patch_id:
            _log.error('patch_id {} does not match with patch_id {}. Ignoring new data.'.format(build.patch_id, patch_id))
            return ERR_UNEXPECTED
        if build.uid != uid:
            _log.error('uid {} does not match with uid {}. Ignoring new data.'.format(build.uid, uid))
            return ERR_UNEXPECTED
        if build.builder_id != builder_id:
            _log.error('builder_id {} does not match with builder_id {}. Ignoring new data.'.format(build.builder_id, builder_id))
            return ERR_UNEXPECTED
        if build.number != number:
            _log.error('build number {} does not match with number {}. Ignoring new data.'.format(build.number, number))
            return ERR_UNEXPECTED
        build.result = result
        build.state_string = state_string
        build.started_at = started_at
        build.complete_at = complete_at
        build.save(update_fields=['result', 'state_string', 'started_at', 'complete_at', 'modified'])
        _log.debug('Updated build {} in database for patch_id: {}'.format(uid, patch_id))
        return SUCCESS

    @classmethod
    def set_retried(cls, uid, retried=True):
        build = Build.get_existing_build(uid)
        if not build:
            return
        build.retried = retried
        build.save(update_fields=['retried', 'modified'])
        _log.info('Updated build {} in database with retried={}'.format(uid, retried))

    @classmethod
    def get_existing_build(cls, uid):
        try:
            return Build.objects.get(uid=uid)
        except Build.DoesNotExist:
            return None

    @classmethod
    def is_valid_result(cls, patch_id, build_id, builder_id, number, result, state_string, started_at, complete_at=None):
        if not (util.is_valid_id(patch_id) and util.is_valid_id(build_id) and util.is_valid_id(builder_id) and util.is_valid_id(number)):
            return False

        return True
