# -*- coding: UTF-8 -*-
#    This file is part of arena.
#
#    arena is free software: you can redistribute it and/or modify it
#    under the terms of the GNU General Public License as published by the
#    Free Software Foundation; either version 3 of the License or, at your
#    option, any later version.
#
#    arena is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABLITY
#    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
#    License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with arena.  If not, see <http://www.gnu.org/licenses/>.

## @file
#  This file expands upon ADataRow in order to provide a
#  standard for "channels", which allow content and content providers to be
#  categorized.

from Library.DataSource.DataRows import ADataRowWithExpandingFields
from Library.IO.Logging.Logs import AMessageWithTimeStamp
from Library.String.Utilities import String

## The delimiter used to separate channel metadata items
chMetaItemsSeparator = "|"
## The delimiter used to separate channel metadata keys from their values
chMetaKeysValuesSeparator = ":="

## A channel, which provides a way to categorize content.
#
#  Within arena, a channel is expected to support the following operations:
#  - fetch -- The channel should be able to fetch its own record from a
#             specified data source.
#  - insert -- The channel can insert its data into a specified data source as
#              a new record.
#  - update -- The channel can update its record within a specified data source
#  - delete -- The channel can delete its record from a specified data source
class AChannel(ADataRowWithExpandingFields):
    ## Construct a new channel instance.
    #
    #  The constructor expects the following values to be present in \p params:
    #  - \p category -- The name of the category in in the data source, within
    #                   which channel definitions are stored.
    def __init__(Self, fieldsValues=None, **params):
        # Set up our expanding field
        params.update({
            "expand": {
                "meta": (dict, chMetaKeysValuesSeparator, chMetaItemsSeparator)
            }
        })
                
        ADataRowWithExpandingFields.__init__(Self, fieldsValues, **params)

    ## Flush changes made to the channel record back to the data source.
    def flush(Self, *criteria):
        if len(Self._changes) > 0:
            if len(criteria) == 0:
                criteria.append(("{field:id} = {}", Self["id"]))
            
            # Remove the "id" field since it is immutable and the data source
            # will complain if we attempt to update it
            del Self._fieldsValues["id"]
                  
            ADataRowWithExpandingFields.flush(Self, *criteria)

    ## Fetch the channel record from the data source.
    def fetch(Self, channelName):
        result = ADataRowWithExpandingFields.fetch(Self, 
            criteria = [
                ("{field:channelName} = {}", channelName)
            ]
        )
                                            
        return result
    
    # Properties ---------------------------------------------------------------        
    ## Return the name of the channel
    def name(Self):
        if "channelName" in Self._fieldsValues:
            return Self["channelName"]
            
        else:
            return ADataRowWithExpandingFields.name(Self)
