# Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
# Copyright (C) 2012 Isaku Yamahata <yamahata at private email ne jp>
#
# 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.


import itertools
import logging
import operator
import os
import sys
import weakref

import ovs.db.data
import ovs.db.types
import ovs.poller
from ovs import (jsonrpc,
                 ovsuuid,
                 stream)
from ovs.db import idl

from ryu.lib import hub
from ryu.lib.ovs import vswitch_idl

LOG = logging.getLogger(__name__)       # use ovs.vlog?


# for debug
def ovsrec_row_changes_to_string(ovsrec_row):
    if not ovsrec_row._changes:
        return ovsrec_row._changes

    return dict((key, value.to_string())
                for key, value in ovsrec_row._changes.items())


# for debug
def ovsrec_row_to_string(ovsrec_row):
    output = ''
    output += 'uuid: %s ' % ovsrec_row.uuid
    if ovsrec_row._data:
        output += '_data: %s ' % dict((key, value.to_string()) for key, value
                                      in ovsrec_row._data.items())
    else:
        output += '_data: %s ' % ovsrec_row._data
    output += '_changes: %s' % ovsrec_row_changes_to_string(ovsrec_row)
    return output


def atom_from_string(base, value_string, symtab=None):
    type_ = base.type
    atom = None
    if type_ == ovs.db.types.IntegerType:
        atom = ovs.db.data.Atom(type_, int(value_string))
    elif type_ == ovs.db.types.RealType:
        # TODO:XXX negation
        atom = ovs.db.data.Atom(
            type_, ovs.db.parser.float_to_int(float(value_string)))
    elif type_ == ovs.db.types.BooleanType:
        if value_string in ("true", "yes", "on", "1"):
            atom = ovs.db.data.Atom(type_, True)
        elif value_string == ("false", "no", "off", "0"):
            atom = ovs.db.data.Atom(type_, False)
    elif type_ == ovs.db.types.StringType:
        # TODO:XXXX escape: if value_string[0] == '"':
        atom = ovs.db.data.Atom(type_, value_string)
    elif type_ == ovs.db.types.UuidType:
        if value_string[0] == "@":
            assert symtab is not None
            uuid_ = symtab[value_string]
            atom = ovs.db.data.Atom(type_, uuid_)
        else:
            atom = ovs.db.data.Atom(type_,
                                    ovs.ovsuuid.from_string(value_string))
    if atom is None:
        raise ValueError("expected %s" % type_.to_string(), value_string)
    atom.check_constraints(base)
    return atom


def datum_from_string(type_, value_string, symtab=None):
    value_string = value_string.strip()
    if type_.is_map():
        if value_string.startswith('{'):
            # TODO:dict case
            LOG.debug('value_string %s', value_string)
            raise NotImplementedError()
        d = dict(v.split('=', 1) for v in value_string.split(','))