# BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# END GPL LICENSE BLOCK #####

bl_info = {
    "name": "Better Bookmarks",
    "description": "Much nicer more user-friendly File Browser bookmarks",
    "author": "Greg Zaal",
    "version": (0, 1),
    "blender": (2, 69, 0),
    "location": "File Browser > Bookmarks Panel on left",
    "warning": "Work in Progress",
    "wiki_url": "",
    "tracker_url": "",
    "category": "System"}

import bpy
from os import sep


config_path = bpy.utils.user_resource('CONFIG')

'''
 TODO:
    Addon prefs for row size
    Custom Icons
    Add Bookmark
'''

def get_bookmarks(return_lines=False):
    bkfile = open(config_path + "BetterBookmarksList", 'r')
    data = bkfile.read().split("\n")
    if not return_lines:
        tmplst = []
        for x in data:
            if x:
                tmplst.append(x.split(":::"))
        for x in tmplst:
            x[0] = int(x[0])
        data = tmplst

    data.sort()
    return data


class BBEdit(bpy.types.Operator):
    """Change the name or path of this bookmark"""
    bl_idname = "better_bookmarks.edit"
    bl_label = "Edit"
    index = bpy.props.IntProperty()

    def execute(self, context):
        scene = context.scene
        bookmarks = get_bookmarks()
        i = self.index

        context.scene.BBEditIndex=i

        scene.BBActiveName = bookmarks[i][1]
        scene.BBActivePath = bookmarks[i][2]

        return {'FINISHED'}

class BBSave(bpy.types.Operator):
    """Save"""
    bl_idname = "better_bookmarks.save"
    bl_label = "Save"
    index = bpy.props.IntProperty()

    def execute(self, context):
        scene = context.scene
        i=self.index
        bookmarks = get_bookmarks()
        bookmarks[i] = [i, scene.BBActiveName, scene.BBActivePath]

        bkfile = open(config_path + "BetterBookmarksList", 'w')
        for bk in bookmarks:
            bkfile.write(str(bk[0])+":::"+bk[1]+":::"+bk[2]+"\n")
        bkfile.close()

        context.scene.BBEditIndex=-1
        return {'FINISHED'}

class BBCancel(bpy.types.Operator):
    """Cancel"""
    bl_idname = "better_bookmarks.cancel"
    bl_label = "Cancel"

    def execute(self, context):
        # Do nothing and exit edit mode
        context.scene.BBEditIndex=-1
        return {'FINISHED'}

class BBUseCurrentPath(bpy.types.Operator):
    """Use Current Path"""
    bl_idname = "better_bookmarks.use_current"
    bl_label = "Use Current Path"

    def execute(self, context):
        context.scene.BBActivePath = context.area.spaces[0].params.directory
        return {'FINISHED'}
        
class BBMove(bpy.types.Operator):
    """Move"""
    bl_idname = "better_bookmarks.move"
    bl_label = "Move"
    index = bpy.props.IntProperty()
    direction = bpy.props.StringProperty()

    def execute(self, context):
        scene = context.scene
        i=self.index
        bookmarks = get_bookmarks()

        if self.direction == 'DOWN':
            if i < len(bookmarks)-1:
                scene.BBEditIndex += 1
                bookmarks[i][0] = i+1
                bookmarks[i+1][0] = i
            else:
                self.report({'ERROR'}, "Bookmark is already at bottom")
        else:
            if i > 0:
                scene.BBEditIndex -= 1
                bookmarks[i][0] = i-1
                bookmarks[i-1][0] = i
            else:
                self.report({'ERROR'}, "Bookmark is already at top")

        bookmarks.sort()
        bkfile = open(config_path + "BetterBookmarksList", 'w')
        for bk in bookmarks:
            bkfile.write(str(bk[0])+":::"+bk[1]+":::"+bk[2]+"\n")
        bkfile.close()
        return {'FINISHED'}

class BBDelete(bpy.types.Operator):
    """Permanently remove this bookmark"""
    bl_idname = "better_bookmarks.delete"
    bl_label = "Delete"
    index = bpy.props.IntProperty()

    def execute(self, context):
        scene = context.scene
        i=self.index
        bookmarks = get_bookmarks()

        del bookmarks[i]
        for bk in bookmarks:
            if bk[0] > i:
                bk[0] = bk[0]-1

        bkfile = open(config_path + "BetterBookmarksList", 'w')
        for bk in bookmarks:
            bkfile.write(str(bk[0])+":::"+bk[1]+":::"+bk[2]+"\n")
        bkfile.close()

        context.scene.BBEditIndex=-1
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_confirm(self, event)


class BBGoto(bpy.types.Operator):
    """Go to this folder"""
    bl_idname = "better_bookmarks.goto"
    bl_label = "Go To Folder"
    path = bpy.props.StringProperty()

    def execute(self, context):
        path_old = context.area.spaces[0].params.directory
        path_new = self.path
        bpy.ops.file.select_bookmark(dir=self.path)

        # catch errors (operator is silent)
        # path_new = context.area.spaces[0].params.directory

        if not path_new.endswith(sep):  # clean slashes off path end in case that's all that's different
            path_new = path_new + sep

        if path_old == context.area.spaces[0].params.directory:
            if path_old != path_new:
                self.report({'ERROR'}, "Unable to go to this folder! Is the path correct?")
        return {'FINISHED'}


class BetterBookmarksPanel(bpy.types.Panel):
    bl_idname = "FILE_PT_bookmarks"
    bl_label = "Better Bookmarks:"
    bl_space_type = 'FILE_BROWSER'
    bl_region_type = 'CHANNELS'

    @classmethod
    def poll(cls, context):
        return (context.space_data.params is not None)

    def draw(self, context):
        layout = self.layout
        scene = context.scene

        col = layout.column()
        bkbox = col.box()

        bookmarks = get_bookmarks()

        bkcol = bkbox.column(align=True)
        i=0
        edit_index = scene.BBEditIndex
        for bk in bookmarks:
            row = bkcol.row()
            row.scale_y=1
            if edit_index == -1 or i != edit_index:
                row.operator('better_bookmarks.goto', icon='BOOKMARKS', emboss=False, text="  "+bk[1]+"                                                                                                                                                                                                                                                            ").path=bk[2]
                row.operator('better_bookmarks.edit', icon="GREASEPENCIL", text="", emboss=False).index=i
            if edit_index >= 0 and i != edit_index:
                row.enabled = False  # grey out the bookmarks that aren't being edited
            elif edit_index >= 0 and i == edit_index:
                #row.separator()
                box = bkcol.box()
                row = box.row(align=True)

                sub = row.column()
                subrow = sub.row(align=True)
                #subrow.scale_y=1.5
                subrow.operator('better_bookmarks.delete', icon="CANCEL", text="", emboss=False).index=i
                subrow.separator()
                subrow.prop(scene, 'BBActiveName', text="")
                subrow.prop(scene, 'BBActivePath', text="")
                subrow.operator('better_bookmarks.use_current', icon="GO_LEFT", text="")
                subrow.separator()
                subrow = sub.row(align=True)
                subrow.separator()
                subrow.operator('better_bookmarks.save', icon="FILE_TICK", emboss=False).index=i
                subrow.operator('better_bookmarks.cancel', icon="LOOP_BACK", emboss=False)

                sub = row.column(align=True)
                m1 = sub.operator('better_bookmarks.move', icon="TRIA_UP", text="")
                m1.index = i
                m1.direction = 'UP'
                m2 = sub.operator('better_bookmarks.move', icon="TRIA_DOWN", text="")
                m2.index = i
                m2.direction = 'DOWN'
            i+=1

        # row = col.row()
        # row.alignment = 'RIGHT'
        # row.operator('better_bookmarks.edit', icon="GREASEPENCIL")


        # col.prop(scene, 'BBProxyData')






def register():
    bpy.types.Scene.BBEditIndex = bpy.props.IntProperty(
        name="INDEX-OF-BOOKMARK-BEING-EDITED",
        default=-1,
        description="Internal Prop")
    bpy.types.Scene.BBProxyData = bpy.props.StringProperty(
        name="PROXY-BOOKMARK-DATA",
        default='-no-bookmarks-',
        description="Internal Prop")
    bpy.types.Scene.BBActiveName = bpy.props.StringProperty(
        name="Name",
        default='',
        description="A short name for this folder, can be different from the actual folder name")
    bpy.types.Scene.BBActivePath = bpy.props.StringProperty(
        name="Path",
        default='',
        description="The full path for this folder")

    bpy.utils.register_module(__name__)


def unregister():
    del bpy.types.Scene.BBEditIndex
    del bpy.types.Scene.BBProxyData

    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()