#
#    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 oslo_db import api as oslo_db_api
from oslo_db import exception as db_exc
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_service import service
from oslo_utils import timeutils
import requests
import six
from six.moves.urllib import parse as urlparse

from heat.common import exception
from heat.common.i18n import _
from heat.common.i18n import _LI
from heat.db import api as db_api
from heat.engine import api
from heat.objects import software_config as software_config_object
from heat.objects import software_deployment as software_deployment_object
from heat.rpc import api as rpc_api

LOG = logging.getLogger(__name__)


class SoftwareConfigService(service.Service):

    def show_software_config(self, cnxt, config_id):
        sc = software_config_object.SoftwareConfig.get_by_id(cnxt, config_id)
        return api.format_software_config(sc)

    def list_software_configs(self, cnxt, limit=None, marker=None,
                              tenant_safe=True):
        scs = software_config_object.SoftwareConfig.get_all(
            cnxt,
            limit=limit,
            marker=marker,
            tenant_safe=tenant_safe)
        result = [api.format_software_config(sc, detail=False) for sc in scs]
        return result

    def create_software_config(self, cnxt, group, name, config,
                               inputs, outputs, options):

        sc = software_config_object.SoftwareConfig.create(cnxt, {
            'group': group,
            'name': name,
            'config': {
                'inputs': inputs,
                'outputs': outputs,
                'options': options,
                'config': config
            },
            'tenant': cnxt.tenant_id})
        return api.format_software_config(sc)

    def delete_software_config(self, cnxt, config_id):
        software_config_object.SoftwareConfig.delete(cnxt, config_id)

    def list_software_deployments(self, cnxt, server_id):
        all_sd = software_deployment_object.SoftwareDeployment.get_all(
            cnxt, server_id)
        result = [api.format_software_deployment(sd) for sd in all_sd]
        return result

    def metadata_software_deployments(self, cnxt, server_id):
        if not server_id:
            raise ValueError(_('server_id must be specified'))
        all_sd = software_deployment_object.SoftwareDeployment.get_all(
            cnxt, server_id)
        # sort the configs by config name, to give the list of metadata a
        # deterministic and controllable order.
        all_sd_s = sorted(all_sd, key=lambda sd: sd.config.name)
        result = [api.format_software_config(sd.config) for sd in all_sd_s]
        return result

    @oslo_db_api.wrap_db_retry(max_retries=10, retry_on_request=True)
    def _push_metadata_software_deployments(self, cnxt, server_id, sd):
        rs = db_api.resource_get_by_physical_resource_id(cnxt, server_id)