# 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.
"""


from django.core import exceptions as django_exceptions
from django.db import models as dbmodels


from autotest_lib.client.common_lib import host_protections
from autotest_lib.client.common_lib import host_states
from autotest_lib.frontend import settings


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 field_dict.iteritems():
            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, such as synch_id. 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, synch_id, 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:
        synch_id: currently unused
        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
    """
    Status = host_states.Status
    hostname = dbmodels.CharField(max_length=255, unique=True)
    locked = dbmodels.BooleanField(default=False)
    leased = dbmodels.BooleanField(default=True)
    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(max_length=255, blank=True, default='')


    class Meta:
        abstract = True


