# 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 enum
from autotest_lib.client.common_lib import host_protections
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 = enum.Enum('Verifying', 'Running', 'Ready', 'Repairing',
                       'Repair Failed', 'Cleaning', 'Pending', 'Resetting',
                       'Provisioning', string_values=True)
    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)


    class Meta:
        abstract = True


