##############################################################################
#
#    Xbus emitter for Odoo
#    Copyright (C) 2015 XCG Consulting <http://odoo.consulting>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import json

from odoo import api, fields, models

from ..util.odoo_context import get_clean_context


class XbusEmitter(models.Model):
    """Configuration profile to emit Xbus messages from Odoo.
    """

    _name = "xbus.emitter"
    _description = "Xbus emitter profile"

    _order = "priority ASC"

    name = fields.Char(string="Name", help="A name for this emitter profile.")

    priority = fields.Integer(
        string="Priority",
        required=True,
        help=(
            "Priority to sort emitter configuration objects; the lowest "
            "priority is the most important."
        ),
        default=100,
    )

    @api.multi
    def send_items(self, event_type, items, chunking="legacy", record=None):
        """Send the data to Xbus, inside one event with the specified event
        type.

        :param event_type: Name of an Xbus event type.
        :type event_type: String.

        :type items: Iterable.

        :param chunking: a default chunking to use to split big items.
        :type chunking: String. Values ("auto", "legacy", "single").

        :param record: A record this message is for. Allows navigating between
        records and their Xbus messages. Optional.
        :type record: Odoo record set.

        :return: The new job.
        :rtype: Odoo "xbus.emitter.job" record set.
        """

        self.ensure_one()

        # Remove default value fillers from the context. This can be called
        # from various places so safer / easier right here than upstream.
        emitter_context = get_clean_context(self)

        job_values = {
            "emitter_id": self.id,
            "event_type": event_type,
            "items": json.dumps(items),
            "chunking": chunking,
        }
        if record:
            job_values.update(
                {"record_id": record.id, "record_model": record._name}
            )
        emitter_job = (
            self.env["xbus.emitter.job"]
            .with_context(emitter_context)
            .create(job_values)
        )

        self._send_notification()

        return emitter_job

    def _send_notification(self):
        """Run a "NOTIFY" postgresql command.
        Since we only tell the external process there is new data in our table,
        the channel name is going to be the table name.
        The payload is the ID of this emitter.

        Ref: <https://www.postgresql.org/docs/current/static/sql-notify.html>.
        """

        self.env.cr.execute(
            "NOTIFY %s, '%s'"
            % (
                self.env["xbus.emitter.job"]._table,
                self.id,
            )  # channel  # payload
        )