# Copyright 2016 Red Hat Inc.
# All Rights Reserved.
#
#    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 neutron_lib.db import constants as db_const
from neutron_lib.db import model_base
from neutron_lib.services.trunk import constants
import sqlalchemy as sa
from sqlalchemy import sql

from neutron.db import models_v2
from neutron.db import standard_attr


class Trunk(standard_attr.HasStandardAttributes, model_base.BASEV2,
            model_base.HasId, model_base.HasProject):

    admin_state_up = sa.Column(
        sa.Boolean(), nullable=False, server_default=sql.true())
    name = sa.Column(sa.String(db_const.NAME_FIELD_SIZE))
    port_id = sa.Column(sa.String(36),
                        sa.ForeignKey('ports.id',
                                      ondelete='CASCADE'),
                        nullable=False,
                        unique=True)
    status = sa.Column(
        sa.String(16), nullable=False,
        server_default=constants.TRUNK_ACTIVE_STATUS)

    port = sa.orm.relationship(
        models_v2.Port,
        backref=sa.orm.backref('trunk_port', lazy='joined', uselist=False,
                               cascade='delete'))

    sub_ports = sa.orm.relationship(
        'SubPort', lazy='subquery', uselist=True, cascade="all, delete-orphan")
    api_collections = ['trunks']
    collection_resource_map = {'trunks': 'trunk'}
    tag_support = True


class SubPort(model_base.BASEV2):

    port_id = sa.Column(sa.String(36),
                        sa.ForeignKey('ports.id',
                                      ondelete='CASCADE'),
                        primary_key=True)
    port = sa.orm.relationship(
        models_v2.Port,
        backref=sa.orm.backref('sub_port', lazy='joined', uselist=False,
                               cascade='delete'))

    trunk_id = sa.Column(sa.String(36),
                         sa.ForeignKey('trunks.id',
                                       ondelete='CASCADE'),
                         nullable=False)

    segmentation_type = sa.Column(sa.String(32), nullable=False)
    segmentation_id = sa.Column(sa.Integer, nullable=False)

    __table_args__ = (
        sa.UniqueConstraint(
            'trunk_id',
            'segmentation_type',
            'segmentation_id',
            name='uniq_subport0trunk_id0segmentation_type0segmentation_id'),
        model_base.BASEV2.__table_args__
    )

# NOTE(armax) constraints like the following are implemented via
# business logic rules:
#
# Deletion of a trunk automatically deletes all of its subports;
# Deletion of a (child) port referred by a subport is forbidden;
# Deletion of a (parent) port referred by a trunk is forbidden;
# A port cannot be a subport and a trunk port at the same time (nested).
