import os
import uuid
from base import StandardMixin, Base
from sqlalchemy import Column, String, Integer, ForeignKey, Table, Float
from sqlalchemy.orm import relationship
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.orderinglist import ordering_list


__all__ = ['Action', 'ExpressionAction', 'GroupAction', 'JointPosition', 'SequenceOrder', 'PoseAction', 'SequenceAction', 'SoundAction', ]


nextActions_table = Table('nextActions', Base.metadata,
    Column('Action_id', Integer, ForeignKey('Action.id')),
    Column('Action_id', Integer, ForeignKey('Action.id'))
)


class Action(StandardMixin, Base):

    name = Column(String(50))
    type = Column(String(50))

    # minimum action length, in seconds
    minLength = Column(Float)
    next_actions = relationship("Action", secondary=nextActions_table)
    triggers = relationship("Trigger", back_populates="action")
    overrides = relationship("CustomAction", back_populates="overridden", foreign_keys="CustomAction.overridden_id")

    __mapper_args__ = {
            'polymorphic_identity': 'Action',
            'polymorphic_on': type
        }

    def __init__(self, name=None, minLength=None, next_actions=[], triggers=[], overrides=[], **kwargs):
        super(Action, self).__init__(**kwargs)
        self.name = name
        self.minLength = minLength
        self.next_actions = next_actions
        self.triggers = triggers
        self.overrides = overrides

    @staticmethod
    def deserialize(cls, dictObj, session, depth=3):
        if cls == Action:
            if dictObj:
                if 'type' in dictObj:
                    actionType = dictObj.pop('type')
                    actionClass = None
                    if actionType.lower() == 'expression':
                        actionClass = ExpressionAction
                    elif actionType.lower() == 'group':
                        actionClass = GroupAction
                    elif actionType.lower() == 'pose':
                        actionClass = PoseAction
                    elif actionType.lower() == 'sequence':
                        actionClass = SequenceAction
                    elif actionType.lower() == 'sound':
                        actionClass = SoundAction
                    else:
                        raise ValueError('Unknown action type: %s' % actionType)

                    return super(cls, cls).deserialize(actionClass, dictObj, session, depth)
                else:
                    raise ValueError('Action type not specified')
            else:
                return None, None
        else:
            return super(cls, cls).deserialize(cls, dictObj, session, depth)


class SoundAction(Action):

    id = Column(Integer, ForeignKey(Action.id), primary_key=True)
    __mapper_args__ = {
            'polymorphic_identity': 'SoundAction',
            'inherit_condition': (id == Action.id),
    }

    uuid = Column(String(36))

    @property
    def data(self):
        if not self.uuid:
            return None

        fileName = self._fileName
        if os.path.isfile(fileName):
            with open(fileName, 'rb') as f:
                b = f.read()
            return b
        else:
            return None

    @property
    def _fileName(self):
        self._basePath = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'soundFiles'))
        if not os.path.isdir(self._basePath):
            os.makedirs(self._basePath)

        if self.uuid == None:
            self.uuid = str(uuid.uuid1())

        return os.path.join(self._basePath, self.uuid)

    @data.setter
    def data(self, value):
        if value:
            with open(self._fileName, 'wb') as f:
                f.write(value)
        elif self.uuid != None:
            os.remove(self._fileName)
            self.uuid = None

    def __init__(self, uuid=None, **kwargs):
        super(SoundAction, self).__init__(**kwargs)
        self.uuid = uuid


class JointPosition(StandardMixin, Base):

    jointName = Column(String(50))
    position = Column(Float)
    positions = Column(String(500))
    speed = Column(Integer)

    pose_id = Column(Integer, ForeignKey('PoseAction.id'))
    pose = relationship("PoseAction", back_populates="jointPositions")

    def __init__(self, jointName=None, position=None, positions=None, speed=None, pose=None, pose_id=None, **kwargs):
        super(JointPosition, self).__init__(**kwargs)
        self.jointName = jointName
        self.positions = positions
        self.position = position
        self.pose = pose
        self.pose_id = pose_id
        self.speed = speed

    def __repr__(self):
        return "<%s('%s':%s)>" % (
                                  self.__class__.__name__,
                                  self.jointName,
                                  self.position)


class PoseAction(Action):

    id = Column(Integer, ForeignKey(Action.id), primary_key=True)
    speedModifier = Column(Integer, default=100, nullable=False)

    __mapper_args__ = {
            'polymorphic_identity': 'PoseAction',
            'inherit_condition': (id == Action.id),
    }

    jointPositions = relationship("JointPosition", back_populates="pose", lazy=False)

    def __init__(self, jointPositions=[], speedModifier=None, **kwargs):
        super(PoseAction, self).__init__(**kwargs)
        self.jointPositions = jointPositions
        self.speedModifier = speedModifier


class ExpressionAction(Action):

    id = Column(Integer, ForeignKey(Action.id), primary_key=True)
    __mapper_args__ = {
            'polymorphic_identity': 'ExpressionAction',
            'inherit_condition': (id == Action.id),
    }

    def __init__(self, **kwargs):
        super(ExpressionAction, self).__init__(**kwargs)


class SequenceAction(Action):

    id = Column(Integer, ForeignKey(Action.id), primary_key=True)

    __mapper_args__ = {
            'polymorphic_identity': 'SequenceAction',
    }

    ordered_actions = relationship("SequenceOrder", order_by="SequenceOrder.order", collection_class=ordering_list("order"), lazy=False)
    actions = association_proxy('ordered_actions', 'action')

    def __init__(self, ordered_actions=[], actions=[], **kwargs):
        super(SequenceAction, self).__init__(**kwargs)
        self.ordered_actions = ordered_actions
        self.actions = actions


class SequenceOrder(StandardMixin, Base):

    order = Column(Integer)

    action_id = Column(Integer, ForeignKey('Action.id'))
    action = relationship("Action", foreign_keys=action_id)

    sequence_id = Column(Integer, ForeignKey('SequenceAction.id'))
    sequence = relationship("SequenceAction", back_populates="ordered_actions", foreign_keys=sequence_id)

    def __init__(self, action=None, action_id=None, sequence=None, sequence_id=None, **kwargs):
        super(SequenceOrder, self).__init__(**kwargs)
        self.action = action
        self.action_id = action_id
        self.sequence = sequence
        self.sequence_id = sequence_id

groupActions_table = Table('groupActions', Base.metadata,
    Column('Group_id', Integer, ForeignKey('GroupAction.id')),
    Column('Action_id', Integer, ForeignKey('Action.id'))
)


class GroupAction(Action):

    id = Column(Integer, ForeignKey(Action.id), primary_key=True)
    __mapper_args__ = {
            'polymorphic_identity': 'GroupAction',
            'inherit_condition': (id == Action.id),
    }

    actions = relationship("Action", secondary=groupActions_table)

    def __init__(self, actions=None, **kwargs):
        super(GroupAction, self).__init__(**kwargs)
        self.actions = actions


@@ -7518,20 +7518,18 @@
 actions=
-None
+%5B%5D
 , **kwar

fix default constructor for groups