# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Model extensions common to both the server and client rdb modules.
"""

import six
from autotest_lib.client.common_lib import host_protections, host_states
from autotest_lib.frontend import settings
from django.core import exceptions as django_exceptions
from django.db import models as dbmodels


class ModelValidators(object):
    """Convenience functions for model validation.

    This model is duplicated both on  the client and server rdb. Any method
    added to this class must only be capable of class level validation of model
    fields, since anything else is meaningless on the client side.
    """
    # TODO: at least some of these functions really belong in a custom
    # Manager class.

    field_dict = None
    # subclasses should override if they want to support smart_get() by name
    name_field = None

    @classmethod
    def get_field_dict(cls):
        if cls.field_dict is None:
            cls.field_dict = {}
            for field in cls._meta.fields:
                cls.field_dict[field.name] = field
        return cls.field_dict


    @classmethod
    def clean_foreign_keys(cls, data):
        """\
        -Convert foreign key fields in data from <field>_id to just
        <field>.
        -replace foreign key objects with their IDs
        This method modifies data in-place.
        """
        for field in cls._meta.fields:
            if not field.rel:
                continue
            if (field.attname != field.name and
                field.attname in data):
                data[field.name] = data[field.attname]
                del data[field.attname]
            if field.name not in data:
                continue
            value = data[field.name]
            if isinstance(value, dbmodels.Model):
                data[field.name] = value._get_pk_val()


    @classmethod
    def _convert_booleans(cls, data):
        """
        Ensure BooleanFields actually get bool values.  The Django MySQL
        backend returns ints for BooleanFields, which is almost always not
        a problem, but it can be annoying in certain situations.
        """
        for field in cls._meta.fields:
            if type(field) == dbmodels.BooleanField and field.name in data:
                data[field.name] = bool(data[field.name])


    # TODO(showard) - is there a way to not have to do this?
    @classmethod
    def provide_default_values(cls, data):
        """\
        Provide default values for fields with default values which have
        nothing passed in.

        For CharField and TextField fields with "blank=True", if nothing
        is passed, we fill in an empty string value, even if there's no
        :retab default set.
        """
        new_data = dict(data)
        field_dict = cls.get_field_dict()
        for name, obj in six.iteritems(field_dict):
            if data.get(name) is not None:
                continue
            if obj.default is not dbmodels.fields.NOT_PROVIDED:
                new_data[name] = obj.default
            elif (isinstance(obj, dbmodels.CharField) or
                  isinstance(obj, dbmodels.TextField)):
                new_data[name] = ''
        return new_data


    @classmethod
    def validate_field_names(cls, data):
        'Checks for extraneous fields in data.'
        errors = {}
        field_dict = cls.get_field_dict()
        for field_name in data:
            if field_name not in field_dict:
                errors[field_name] = 'No field of this name'
        return errors


    @classmethod
    def prepare_data_args(cls, data):
        'Common preparation for add_object and update_object'
        # must check for extraneous field names here, while we have the
        # data in a dict
        errors = cls.validate_field_names(data)
        if errors:
            raise django_exceptions.ValidationError(errors)
        return data


    @classmethod
    def _get_required_field_names(cls):
        """Get the fields without which we cannot create a host.

        @return: A list of field names that cannot be blank on host creation.
        """
        return [field.name for field in cls._meta.fields if not field.blank]


    @classmethod
    def get_basic_field_names(cls):
        """Get all basic fields of the Model.

        This method returns the names of all fields that the client can provide
        a value for during host creation. The fields not included in this list
        are those that we can leave blank. Specifying non-null values for such
        fields only makes sense as an update to the host.

        @return A list of basic fields.
            Eg: set([hostname, locked, leased, status, invalid,
                     protection, lock_time, dirty])
        """
        return [field.name for field in cls._meta.fields
                if field.has_default()] + cls._get_required_field_names()


    @classmethod
    def validate_model_fields(cls, data):
        """Validate parameters needed to create a host.

        Check that all required fields are specified, that specified fields
        are actual model values, and provide defaults for the unspecified
        but unrequired fields.

        @param dict: A dictionary with the args to create the model.

        @raises dajngo_exceptions.ValidationError: If either an invalid field
            is specified or a required field is missing.
        """
        missing_fields = set(cls._get_required_field_names()) - set(data.keys())
        if missing_fields:
            raise django_exceptions.ValidationError('%s required to create %s, '
                    'supplied %s ' % (missing_fields, cls.__name__, data))
        data = cls.prepare_data_args(data)
        data = cls.provide_default_values(data)
        return data


class AbstractHostModel(dbmodels.Model, ModelValidators):
    """Abstract model specifying all fields one can use to create a host.

    This model enforces consistency between the host models of the rdb and
    their representation on the client side.

    Internal fields:
        status: string describing status of host
        invalid: true if the host has been deleted
        protection: indicates what can be done to this host during repair
        lock_time: DateTime at which the host was locked
        dirty: true if the host has been used without being rebooted
        lock_reason: The reason for locking the host.
    """
    Status = host_states.Status
    hostname = dbmodels.CharField(max_length=255, unique=True)
    locked = dbmodels.BooleanField(default=False)
    leased = dbmodels.BooleanField(default=True)
    # TODO(ayatane): This is needed until synch_id is removed from Host._fields
    synch_id = dbmodels.IntegerField(blank=True, null=True,
                                     editable=settings.FULL_ADMIN)
    status = dbmodels.CharField(max_length=255, default=Status.READY,
                                choices=Status.choices(),
                                editable=settings.FULL_ADMIN)
    invalid = dbmodels.BooleanField(default=False,
                                    editable=settings.FULL_ADMIN)
    protection = dbmodels.SmallIntegerField(null=False, blank=True,
                                            choices=host_protections.choices,
                                            default=host_protections.default)
    lock_time = dbmodels.DateTimeField(null=True, blank=True, editable=False)
    dirty = dbmodels.BooleanField(default=True, editable=settings.FULL_ADMIN)
    lock_reason = dbmodels.CharField(null=True, max_length=255, blank=True,
                                     default='')


    class Meta:
        """Extends dbmodels.Model.Meta"""
        abstract = True
