#!/usr/bin/env python
# coding=utf-8
"""
Soundforest database manipulation tool
"""

import os
import sys
import re
import shutil
import argparse

from soundforest import SoundforestError
from soundforest.cli import Script, ScriptCommand, ScriptError
from soundforest.tree import Tree, Track, Album

class CodecsCommand(ScriptCommand):
    def run(self, args):
        ScriptCommand.run(self, args)

        if args.action == 'list':
            for name, codec in self.db.codecs.items():
                print '%s (%s)' % (codec, codec.description)
                print 'Extensions'
                print '  %s' %  ','.join(x.extension for x in codec.extensions)
                print 'Decoders'
                for decoder in codec.decoders: print '  ', decoder.command
                print 'Encoders'
                for encoder in codec.encoders: print '  ', encoder.command
                print


class ConfigCommand(ScriptCommand):
    def run(self, args):
        ScriptCommand.run(self, args)

        if args.action == 'list':
            for setting in self.db.registered_settings:
                print '%16s %s' % (setting.key, setting.value)


class PlaylistsCommand(ScriptCommand):
    def run(self, args):
        ScriptCommand.run(self, args)

        if args.action == 'list':
            for playlist in self.db.playlists:
                print playlist


class SyncConfigCommand(ScriptCommand):
    def run(self, args):
        ScriptCommand.run(self, args)

        if args.action == 'list':
            for s in self.db.registered_sync_targets:
                print s

        if args.action == 'register':
            print 'Registering sync target %s' % args.name
            self.db.register_sync_target(args.name, args.type, args.src, args.dst, args.flags)


class TagsCommand(ScriptCommand):
    def run(self, args):
        ScriptCommand.run(self, args)

        if args.action == 'list':
            if args.tree:
                trees = [self.db.get_tree(args.tree)]
            else:
                trees = self.db.trees

            for tree in trees:
                for path in args.paths:
                    for track in tree.filter_tracks(self.db.session, path):
                        for entry in track.tags:
                            print '  %s = %s' % (entry.tag, entry.value)


class TracksCommand(ScriptCommand):
    def run(self, args):
        ScriptCommand.run(self, args)

        if args.action == 'list':
            if args.tree:
                trees = [self.db.get_tree(args.tree)]
            else:
                trees = self.db.trees

            for tree in trees:
                for path in args.paths:
                    for track in tree.filter_tracks(self.db.session, path):
                        print track.relative_path


class TreeCommand(ScriptCommand):
    def run(self, args):
        ScriptCommand.run(self, args)

        if args.paths:
            args.paths = [x.rstrip(os.sep) for x in args.paths]

        if args.tree_type and args.tree_type not in script.db.registered_tree_types:
            self.script.exit(1, 'Unsupported tree type: %s' % args.tree_type)

        if args.action == 'register':
            for path in args.paths:
                self.db.register_tree(path, tree_type=args.tree_type)

        if args.action == 'unregister':
            for path in args.paths:
                self.db.unregister_tree(path)

        if args.action == 'update':
            for tree in self.db.trees:
                if args.paths and tree.path not in args.paths:
                    continue
                self.db.update_tree(Tree(tree.path))

        if args.action == 'list':
            for tree in self.db.trees:
                if args.tree_type and tree.type != args.tree_type:
                    continue

                if args.paths and not self.match_path(tree.path, args.paths):
                    continue

                print tree


class TreeTypesCommand(ScriptCommand):
    def run(self, args):
        ScriptCommand.run(self, args)

        if args.action == 'list':
            for tt in self.db.registered_tree_types:
                print '%14s %s' % (tt.name, tt.description)

        if args.action == 'register':
            for tt in args.types:
                self.db.register_tree_type(tt)

        if args.action == 'unregister':
            for tt in args.types:
                self.db.unregister_tree_type(tt)


# Register parser and sub commands
script = Script()
c = script.add_subcommand(CodecsCommand('codec', 'Codec database manipulations'))
c.add_argument('-v', '--verbose', action='store_true', help='Verbose details')
c.add_argument('action', choices=('list',), help='Codec database action')

c = script.add_subcommand(ConfigCommand('config', 'Configuration database manipulations'))
c.add_argument('action', choices=('list',), help='List trees in database')
c.add_argument('-v', '--verbose', action='store_true', help='Verbose details')

c = script.add_subcommand(PlaylistsCommand('playlist', 'Playlist database manipulations'))
c.add_argument('-t', '--tree', help='Tree to match')
c.add_argument('action', choices=('list',), help='List trees in database')
c.add_argument('paths', nargs='*', help='Paths to trees to process')

c = script.add_subcommand(SyncConfigCommand('sync-config', 'Manage tree sync configurations'))
c.add_argument('action', choices=('list', 'register', 'unregister',), help='Action to perform')
c.add_argument('name', nargs='?', help='Sync target name')
c.add_argument('type', choices=('rsync', 'directory',), nargs='?', help='Sync type')
c.add_argument('flags', nargs='?', help='Flags for sync command')
c.add_argument('src', nargs='?', help='Source path')
c.add_argument('dst', nargs='?', help='Destination path')

c = script.add_subcommand(TagsCommand('tag', 'Track tag database manipulations'))
c.add_argument('-t', '--tree', help='Tree to match')
c.add_argument('action', choices=('list',), help='List trees in database')
c.add_argument('paths', nargs='*', help='Paths to trees to process')

c = script.add_subcommand(TracksCommand('track', 'Tree database manipulations'))
c.add_argument('-t', '--tree', help='Tree to match')
c.add_argument('action', choices=('list',), help='List trees in database')
c.add_argument('paths', nargs='*', help='Paths to trees to process')

c = script.add_subcommand(TreeCommand('tree', description = 'Tree database manipulations'))
c.add_argument('-t', '--tree-type', help='Type of audio files in tree')
c.add_argument('action', choices=('list', 'update', 'register', 'unregister'), help='List trees in database')
c.add_argument('paths', nargs='*', help='Paths to trees to process')

c = script.add_subcommand(TreeTypesCommand('tree-type', description = 'Tree type database manipulations'))
c.add_argument('action', choices=('list', 'register', 'unregister'), help='List tree types in database')
c.add_argument('types', nargs='*', help='Tree type names to process')

script.run()



