import click

from ffx.model.track import Track

from ffx.model.media_tag import MediaTag
from ffx.model.track_tag import TrackTag


class TagController():
    
    def __init__(self, context):
        
        self.context = context
        self.Session = self.context['database']['session'] # convenience


    def updateMediaTag(self, patternId, tagKey, tagValue):

        try:
            s = self.Session()

            q = s.query(MediaTag).filter(MediaTag.pattern_id == int(patternId),
                                MediaTag.key == str(tagKey))
            tag = q.first()
            if tag:
                tag.value = str(tagValue)
            else:
                tag = MediaTag(pattern_id = int(patternId),
                                key = str(tagKey),
                                value = str(tagValue))
                s.add(tag)
            s.commit()

            return int(tag.id)

        except Exception as ex:
            raise click.ClickException(f"TagController.updateTrackTag(): {repr(ex)}")
        finally:
            s.close()

    def updateTrackTag(self, trackId, tagKey, tagValue):

        try:
            s = self.Session()

            q = s.query(TrackTag).filter(TrackTag.track_id == int(trackId),
                                TrackTag.key == str(tagKey))
            tag = q.first()
            if tag:
                tag.value = str(tagValue)
            else:
                tag = TrackTag(track_id = int(trackId),
                                key = str(tagKey),
                                value = str(tagValue))
                s.add(tag)
            s.commit()

            return int(tag.id)

        except Exception as ex:
            raise click.ClickException(f"TagController.updateTrackTag(): {repr(ex)}")
        finally:
            s.close()

    def deleteMediaTagByKey(self, patternId, tagKey):

        try:
            s = self.Session()

            tag = s.query(MediaTag).filter(
                MediaTag.pattern_id == int(patternId),
                MediaTag.key == str(tagKey),
            ).first()
            if tag is not None:
                s.delete(tag)
                s.commit()
                return True
            else:
                return False

        except Exception as ex:
            raise click.ClickException(f"TagController.deleteMediaTagByKey(): {repr(ex)}")
        finally:
            s.close()

    def deleteTrackTagByKey(self, trackId, tagKey):

        try:
            s = self.Session()

            q = s.query(TrackTag).filter(TrackTag.track_id == int(trackId),
                                TrackTag.key == str(tagKey))
            tag = q.first()
            if tag:
                s.delete(tag)
                s.commit()
                return True
            else:
                return False

        except Exception as ex:
            raise click.ClickException(f"TagController.deleteTrackTagByKey(): {repr(ex)}")
        finally:
            s.close()

    def findAllMediaTags(self, patternId) -> dict:

        try:
            s = self.Session()
                
            tags = s.query(MediaTag).filter(MediaTag.pattern_id == int(patternId)).all()
            return {t.key:t.value for t in tags}

        except Exception as ex:
            raise click.ClickException(f"TagController.findAllMediaTags(): {repr(ex)}")
        finally:
            s.close()


    def findAllTrackTags(self, trackId) -> dict:

        try:
            s = self.Session()
                
            tags = s.query(TrackTag).filter(TrackTag.track_id == int(trackId)).all()
            return {t.key:t.value for t in tags}

        except Exception as ex:
            raise click.ClickException(f"TagController.findAllTracks(): {repr(ex)}")
        finally:
            s.close()


    def findMediaTag(self, trackId : int, trackKey : str) -> MediaTag:
        
        try:
            s = self.Session()
            return s.query(Track).filter(MediaTag.track_id == int(trackId), MediaTag.key == str(trackKey)).first()

        except Exception as ex:
            raise click.ClickException(f"TagController.findMediaTag(): {repr(ex)}")
        finally:
            s.close()

    def findTrackTag(self, trackId : int, tagKey : str) -> TrackTag:
        
        try:
            s = self.Session()
            return s.query(TrackTag).filter(
                TrackTag.track_id == int(trackId),
                TrackTag.key == str(tagKey),
            ).first()

        except Exception as ex:
            raise click.ClickException(f"TagController.findTrackTag(): {repr(ex)}")
        finally:
            s.close()



    def deleteMediaTag(self, tagId) -> bool:
        try:
            s = self.Session()
            tag = s.query(MediaTag).filter(MediaTag.id == int(tagId)).first()

            if tag is not None:

                s.delete(tag)

                s.commit()
                return True

            return False

        except Exception as ex:
            raise click.ClickException(f"TagController.deleteMediaTag(): {repr(ex)}")
        finally:
            s.close()


    def deleteTrackTag(self, tagId : int) -> bool:

        if type(tagId) is not int:
            raise TypeError('TagController.deleteTrackTag(): Argument tagId is required to be of type int')

        try:
            s = self.Session()
            tag = s.query(TrackTag).filter(TrackTag.id == int(tagId)).first()

            if tag is not None:

                s.delete(tag)

                s.commit()
                return True

            return False

        except Exception as ex:
            raise click.ClickException(f"TagController.deleteTrackTag(): {repr(ex)}")
        finally:
            s.close()
