# Path: ecell4/util/model_parser.py
# class Visitor(object):
# 
#     def visit_const(self, obj):
#         return self.visit_default(obj)
# 
#     def visit_species(self, obj):
#         return self.visit_default(obj)
# 
#     def visit_quantity(self, obj):
#         return self.visit_default(obj)
# 
#     def visit_func(self, obj, *args):
#         return self.visit_default(obj)
# 
#     def visit_expression(self, obj, *args):
#         return self.visit_default(obj)
# 
#     def visit_default(self, obj):
#         return obj
# 
# def dispatch(obj, visitor):
#     if isinstance(obj, parseobj.AnyCallable):
#         obj = obj._as_ParseObj()
# 
#     if isinstance(obj, parseobj.ParseObj):
#         if obj._size() == 1 and obj._elems[0].name in RATELAW_RESERVED_FUNCTIONS:
#             # function
#             subobj = obj._elems[0]
#             assert subobj.key is None
#             assert subobj.modification is None
#             assert ((subobj.args is not None and subobj.kwargs == {})
#                     or (subobj.args is None and subobj.kwargs is None))
#             args = [dispatch(subobj.args[i], visitor) for i in range(len(subobj.args))]
#             return visitor.visit_func(obj, *args)
#         elif obj._size() == 1 and obj._elems[0].name in RATELAW_RESERVED_CONSTANTS:
#             # constant
#             subobj = obj._elems[0]
#             assert subobj.key is None
#             assert subobj.modification is None
#             assert subobj.args is None
#             assert subobj.kwargs is None
#             return visitor.visit_const(obj)
#         else:
#             # species
#             return visitor.visit_species(obj)
#     elif isinstance(obj, parseobj.ExpBase):
#         args = [dispatch(obj._elems[i], visitor) for i in range(len(obj._elems))]
#         return visitor.visit_expression(obj, *args)
#     # elif isinstance(obj, unit._Quantity):
#     #     return visitor.visit_quantity(obj)
#     else:
#         return visitor.visit_default(obj)
# 
# RATELAW_RESERVED_FUNCTIONS = {
#     'pow': numpy.power, 'exp': numpy.exp, 'log': numpy.log,
#     'sin': numpy.sin, 'cos': numpy.cos, 'tan': numpy.tan,
#     'asin': numpy.arcsin, 'acos': numpy.arccos, 'atan': numpy.arctan,
#     'abs': numpy.fabs, 'sqrt': numpy.sqrt,
#     }
# 
# RATELAW_RESERVED_CONSTANTS = {
#     '_t': None,  #XXX: just reserved
#     '_v': None,  #XXX: just reserved
#     '_rc': None,  #XXX: just reserved
#     '_pc': None,  #XXX: just reserved
#     'pi': math.pi
#     }


import os
import os.path
    import base64
import ecell4_base
    import numpy
from tempfile import NamedTemporaryFile
    from ecell4_base.core import Real3
        from IPython.display import display, HTML
from ..util.model_parser import Visitor, dispatch, RATELAW_RESERVED_FUNCTIONS, RATELAW_RESERVED_CONSTANTS
    from ecell4.util.decorator_base import just_parse

def display_anim(ani, output=None, fps=6, crf=10, bitrate='1M'):
    if output is None:
        display(HTML(anim_to_html(ani, output, fps=fps, crf=crf, bitrate=bitrate)))
    elif os.path.splitext(output.lower())[1] == '.webm':
        ani.save(output, fps=fps, codec='libvpx', extra_args=['-auto-alt-ref', '0', '-crf', str(crf), '-b:v', bitrate])
    elif os.path.splitext(output.lower())[1] == '.mp4':
        ani.save(output, fps=fps, codec='mpeg4', extra_args=['-crf', str(crf), '-b:v', bitrate])
    else:
        raise ValueError(
            "An output filename is only accepted with extension '.webm' or 'mp4'.")


class EvalVisitor(Visitor):

    def __init__(self, variables):
        self.variables = variables

    def visit_const(self, obj):
        if str(obj) not in RATELAW_RESERVED_CONSTANTS:
            raise ValueError()
        return RATELAW_RESERVED_CONSTANTS[str(obj)]

    def visit_species(self, obj):
        pttrn = ecell4_base.core.Species(str(obj))
        return sum(ecell4_base.core.count_species_matches(pttrn, key) * value for key, value in self.variables.items())

    def visit_func(self, obj, *args):
        print(obj)
        assert obj._elems[0].name in RATELAW_RESERVED_FUNCTIONS

# Path: ecell4/util/model_parser.py
# class Visitor(object):
# 
#     def visit_const(self, obj):
#         return self.visit_default(obj)
# 
#     def visit_species(self, obj):
#         return self.visit_default(obj)
# 
#     def visit_quantity(self, obj):
#         return self.visit_default(obj)
# 
#     def visit_func(self, obj, *args):
#         return self.visit_default(obj)
# 
#     def visit_expression(self, obj, *args):
#         return self.visit_default(obj)
# 
#     def visit_default(self, obj):
#         return obj
# 
# def dispatch(obj, visitor):
#     if isinstance(obj, parseobj.AnyCallable):
#         obj = obj._as_ParseObj()
# 
#     if isinstance(obj, parseobj.ParseObj):
#         if obj._size() == 1 and obj._elems[0].name in RATELAW_RESERVED_FUNCTIONS:
#             # function
#             subobj = obj._elems[0]
#             assert subobj.key is None
#             assert subobj.modification is None
#             assert ((subobj.args is not None and subobj.kwargs == {})
#                     or (subobj.args is None and subobj.kwargs is None))
#             args = [dispatch(subobj.args[i], visitor) for i in range(len(subobj.args))]
#             return visitor.visit_func(obj, *args)
#         elif obj._size() == 1 and obj._elems[0].name in RATELAW_RESERVED_CONSTANTS:
#             # constant
#             subobj = obj._elems[0]
#             assert subobj.key is None
#             assert subobj.modification is None
#             assert subobj.args is None
#             assert subobj.kwargs is None
#             return visitor.visit_const(obj)
#         else:
#             # species
#             return visitor.visit_species(obj)
#     elif isinstance(obj, parseobj.ExpBase):
#         args = [dispatch(obj._elems[i], visitor) for i in range(len(obj._elems))]
#         return visitor.visit_expression(obj, *args)
#     # elif isinstance(obj, unit._Quantity):
#     #     return visitor.visit_quantity(obj)
#     else:
#         return visitor.visit_default(obj)
# 
# RATELAW_RESERVED_FUNCTIONS = {
#     'pow': numpy.power, 'exp': numpy.exp, 'log': numpy.log,
#     'sin': numpy.sin, 'cos': numpy.cos, 'tan': numpy.tan,
#     'asin': numpy.arcsin, 'acos': numpy.arccos, 'atan': numpy.arctan,
#     'abs': numpy.fabs, 'sqrt': numpy.sqrt,
#     }
# 
# RATELAW_RESERVED_CONSTANTS = {
#     '_t': None,  #XXX: just reserved
#     '_v': None,  #XXX: just reserved
#     '_rc': None,  #XXX: just reserved
#     '_pc': None,  #XXX: just reserved
#     'pi': math.pi
#     }


# Path: ecell4/plotting/_core.py
import os
import os.path
    import base64
import ecell4_base
    import numpy
from tempfile import NamedTemporaryFile
    from ecell4_base.core import Real3
        from IPython.display import display, HTML
from ..util.model_parser import Visitor, dispatch, RATELAW_RESERVED_FUNCTIONS, RATELAW_RESERVED_CONSTANTS
    from ecell4.util.decorator_base import just_parse


def display_anim(ani, output=None, fps=6, crf=10, bitrate='1M'):
    if output is None:
        display(HTML(anim_to_html(ani, output, fps=fps, crf=crf, bitrate=bitrate)))
    elif os.path.splitext(output.lower())[1] == '.webm':
        ani.save(output, fps=fps, codec='libvpx', extra_args=['-auto-alt-ref', '0', '-crf', str(crf), '-b:v', bitrate])
    elif os.path.splitext(output.lower())[1] == '.mp4':
        ani.save(output, fps=fps, codec='mpeg4', extra_args=['-crf', str(crf), '-b:v', bitrate])
    else:
        raise ValueError(
            "An output filename is only accepted with extension '.webm' or 'mp4'.")


class EvalVisitor(Visitor):

    def __init__(self, variables):
        self.variables = variables

    def visit_const(self, obj):
        if str(obj) not in RATELAW_RESERVED_CONSTANTS:
            raise ValueError()
        return RATELAW_RESERVED_CONSTANTS[str(obj)]

    def visit_species(self, obj):
        pttrn = ecell4_base.core.Species(str(obj))
        return sum(ecell4_base.core.count_species_matches(pttrn, key) * value for key, value in self.variables.items())

    def visit_func(self, obj, *args):
        print(obj)
        assert obj._elems[0].name in RATELAW_RESERVED_FUNCTIONS

        return RATELAW_RESERVED_FUNCTIONS[obj._elems[0].name](*args)