#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 1999-2022 Alibaba Group Holding Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .core import LazyLoad
from .resource import Resource
from .. import serializers, utils


class Function(LazyLoad):
    """
    Function can be used in UDF when user writes a SQL.
    """
    __slots__ = '_resources_objects', '_owner_changed'

    _root = 'Function'

    name = serializers.XMLNodeField('Alias')
    _owner = serializers.XMLNodeField('Owner')
    creation_time = serializers.XMLNodeField('CreationTime', parse_callback=utils.parse_rfc822)
    class_type = serializers.XMLNodeField('ClassType')
    _resources = serializers.XMLNodesField('Resources', 'ResourceName')
    is_sql_function = serializers.XMLNodeField('IsSqlFunction')
    is_embedded_function = serializers.XMLNodeField('IsEmbeddedFunction')
    program_language = serializers.XMLNodeField('ProgramLanguage')
    code = serializers.XMLNodeField('Code')
    file_name = serializers.XMLNodeField('FileName')

    def __init__(self, **kwargs):
        self._resources_objects = None
        self._owner_changed = False

        resources = kwargs.pop('resources', None)
        if 'owner' in kwargs:
            kwargs['_owner'] = kwargs.pop('owner')
        super(Function, self).__init__(**kwargs)
        if resources is not None:
            self.resources = resources

    def reload(self):
        resp = self._client.get(
            self.resource(), curr_schema=self._get_schema_name()
        )
        self.parse(self._client, resp, obj=self)

    @property
    def resources(self):
        """
        Return all the resources which this function refer to.

        :return: resources
        :rtype: list

        .. seealso:: :class:`odps.models.Resource`
        """

        if self._resources_objects is not None:
            return self._resources_objects

        resources = self.parent.parent.resources
        resources = [resources[name] for name in self._resources or ()]
        self._resources_objects = resources
        return resources

    @resources.setter
    def resources(self, value):
        def get_resource_name(res):
            if isinstance(res, Resource):
                schema_name = res._get_schema_name()
                if res.project.name == self.project.name and schema_name is None:
                    return res.name
                return res.full_resource_name
            else:
                return res

        self._resources_objects = None
        self._resources = [get_resource_name(res) for res in value]

    @property
    def owner(self):
        return self._owner

    @owner.setter
    def owner(self, value):
        self._owner_changed = True
        self._owner = value

    def update(self):
        """
        Update this function.

        :return: None
        """
        if self._owner_changed:
            self.update_owner(self.owner)

        self._resources = [res.name for res in self.resources]
        return self.parent.update(self)

    def update_owner(self, new_owner):
        params = {}
        schema_name = self._get_schema_name()
        if schema_name:
            params['curr_schema'] = schema_name

        headers = {
            'x-odps-owner': new_owner
        }
        self._client.put(
            self.resource(), None, action="updateowner", params=params, headers=headers
        )

    def drop(self):
        """
        Delete this Function.

        :return: None
        """

        return self.parent.delete(self)
