/*
SRBookmarkMenuProvider.m

Author: Makoto Kinoshita

Copyright 2004-2006 The Shiira Project. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted 
provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions 
  and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of 
  conditions and the following disclaimer in the documentation and/or other materials provided 
  with the distribution.

THIS SOFTWARE IS PROVIDED BY THE SHIIRA PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE SHIIRA PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
*/

#import "SRBookmark.h"

#import "SRAppController.h"
#import "SRBookmarkMenuProvider.h"
#import "SRMenu.h"

#import "SRConstants.h"

#import "SRPrefDefaultKeys.h"

// Consntats
int  SRNumberOfDefaultBookmarkMenu = 6;

@implementation SRBookmarkMenuProvider

//--------------------------------------------------------------//
#pragma mark -- Initialize --
//--------------------------------------------------------------//

+ (id)sharedInstance
{
    static SRBookmarkMenuProvider*  _sharedInstance = nil;
    if (!_sharedInstance) {
        _sharedInstance = [[SRBookmarkMenuProvider alloc] init];
    }
    
    return _sharedInstance;
}

//--------------------------------------------------------------//
#pragma mark -- NSMenu delegate --
//--------------------------------------------------------------//

- (BOOL)menuHasKeyEquivalent:(NSMenu*)menu 
        forEvent:(NSEvent*)event 
        target:(id*)target 
        action:(SEL*)action
{
    return NO;
}

- (void)menuNeedsUpdate:(NSMenu*)menu
{
    if ([menu delegate] != self) {
        return;
    }
    
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get bookmark for bookmark bar
    SRBookmark* bookmarkBarBookmark;
    bookmarkBarBookmark = [[SRAppController sharedInstance] bookmarkForBookmarkBar];
    
    // Get root bookmark
    id  rootBookmark;
    rootBookmark = [[SRAppController sharedInstance] rootBookmarkOfBrowser:SRBrowserShiira];
#if 0
    // Get bookmarks menu
    NSArray*    shiiraBookmarksMenu;
    SRBookmark* safariBookmarksMenu;
    SRBookmark* firefoxBookmarksMenu;
    shiiraBookmarksMenu = [bookmarkStorage shiiraBookmarksMenu];
    safariBookmarksMenu = [bookmarkStorage safariBookmarksMenu];
    firefoxBookmarksMenu = [bookmarkStorage firefoxBookmarks];
    
    // Get menu avaialability
    NSArray*    isUsing;
    isUsing = [defaults objectForKey:SRBookmarkIsUsing];
#endif
    
    NSMenuItem* menuItem;
    
    // For bookmark menu
    if (menu == SRBookmarkMenu()) {
        // Remove old bookmarks
        int i;
        for (i = [menu numberOfItems] - 1; i > SRNumberOfDefaultBookmarkMenu - 1; i--) {
            [menu removeItemAtIndex:i];
        }
        
        // Bookmarks bar
        if (bookmarkBarBookmark) {
            // Create bookmarks bar item
            menuItem = [[NSMenuItem alloc] 
                    initWithTitle:[bookmarkBarBookmark title] action:NULL keyEquivalent:@""];
            [menuItem autorelease];
            [menuItem setImage:[bookmarkBarBookmark icon]];
            
            // Create bookmarks bar menu
            SRMenu*     bookmarksBarMenu;
            bookmarksBarMenu = [[SRMenu alloc] initWithTitle:@"Bookmarks bar"];
            [bookmarksBarMenu autorelease];
            [bookmarksBarMenu setRepresentedObject:bookmarkBarBookmark];
            [bookmarksBarMenu setDelegate:self];
            [menuItem setSubmenu:bookmarksBarMenu];
            
            // Add bookmarks bar
            [menu addItem:menuItem];
            [menu addItem:[NSMenuItem separatorItem]];
        }
        
        // Appned bookmarks
        NSMutableArray* bookmarks;
        bookmarks = [NSMutableArray arrayWithArray:[rootBookmark sortedChildren]];
        [bookmarks removeObject:bookmarkBarBookmark];
        
        SRAppendBookmarksIntoMenu(bookmarks, menu, YES);
#if 0
        // Safari bookmark availability
        BOOL    isSafariAvailable = NO;
        if ([isUsing count] > SRBrowserSafari) {
            isSafariAvailable = [[isUsing objectAtIndex:SRBrowserSafari] boolValue];
        }
        
        // Firefox bookmark availability
        BOOL    isFirefoxAvailable = NO;
        if ([isUsing count] > SRBrowserFirefox) {
            isFirefoxAvailable = [[isUsing objectAtIndex:SRBrowserFirefox] boolValue];
        }
        
        // Shiira bookmarks menu
        if (shiiraBookmarksMenu && [shiiraBookmarksMenu count] > 0) {
            // When it has only Shiira menu, dose not include menu title
            if (isSafariAvailable || isFirefoxAvailable) {
                menuItem = (NSMenuItem*)[menu addItemWithTitle:
                        [NSString stringWithFormat:@"- %@ -", 
                                NSLocalizedStringFromTable(@"ShiiraBookmarks", @"Bookmark", @"Shiira Bookmarks")] 
                        action:NULL 
                        keyEquivalent:@""];
                [menuItem setEnabled:NO];
            }
            SRAppendBookmarksIntoMenu(shiiraBookmarksMenu, menu, YES);
        }
        
        // Safari bookmarks menu
        if (isSafariAvailable && safariBookmarksMenu && [[safariBookmarksMenu children] count] > 0) {
            // Add separator
            [menu addItem:[NSMenuItem separatorItem]];
            
            // Add Safari bookmarks menu
            menuItem = (NSMenuItem*)[menu addItemWithTitle:
                    [NSString stringWithFormat:@"- %@ -", 
                            NSLocalizedStringFromTable(@"SafariBookmarks", @"Bookmark", @"Safari Bookmarks")] 
                    action:NULL 
                    keyEquivalent:@""];
            [menuItem setEnabled:NO];
            SRAppendBookmarksIntoMenu([safariBookmarksMenu children], menu, YES);
        }
        
        // Firefox bookmarks menu
        if (isFirefoxAvailable && firefoxBookmarksMenu && [[firefoxBookmarksMenu children] count] > 0) {
            // Add separator
            [menu addItem:[NSMenuItem separatorItem]];
            
            // Add Firefox bookmarks menu
            menuItem = (NSMenuItem*)[menu addItemWithTitle:
                    [NSString stringWithFormat:@"- %@ -", 
                            NSLocalizedStringFromTable(@"FirefoxBookmarks", @"Bookmark", @"Firefox Bookmarks")] 
                    action:NULL 
                    keyEquivalent:@""];
            [menuItem setEnabled:NO];
            SRAppendBookmarksIntoMenu([firefoxBookmarksMenu children], menu, YES);
        }
#endif
    }
    // Other sub menu
    else {
        if ([menu isKindOfClass:[SRMenu class]]) {
            // Get represented object
            id  object;
            object = [(SRMenu*)menu representedObject];
            if (object) {
                SRBookmark* bookmark;
                bookmark = (SRBookmark*)object;
                
                // Append boomarks
                NSArray*    children;
                children = [[bookmark valueForKey:@"children"] allObjects];
                if ([children count] > 0) {
                    SRAppendBookmarksIntoMenu(HMSortWithKey(children, @"index", YES), menu, YES);
                }
            }
        }
    }
}

@end

//--------------------------------------------------------------//
#pragma mark -- Utility --
//--------------------------------------------------------------//

void SRAppendBookmarksIntoMenu(
        NSArray* bookmarks, 
        NSMenu* menu, 
        BOOL bookmarkBarShortCut)
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Enumerate bookmark
    NSEnumerator*   enumerator;
    SRBookmark*     bookmark;
    NSMenuItem*     menuItem;
    int             shortCut = 1;
    enumerator = [bookmarks objectEnumerator];
    while (bookmark = [enumerator nextObject]) {
        // Case of not folder type
        if (![[bookmark isFolder] boolValue]) {
            // Check parent
            BOOL        isBookmarkBar;
            NSString*   shortCutKey = @"";
            isBookmarkBar = [[[bookmark valueForKey:@"parent"] 
                    valueForKey:@"type"] isEqualToString:SRBookmarkTypeBookmarkBar];
            if (isBookmarkBar && bookmarkBarShortCut) {
                if (shortCut < 10) {
                    shortCutKey = [NSString stringWithFormat:@"%d", shortCut++];
                }
            }
            
            // Create menu item
            menuItem = [menu addItemWithTitle:[bookmark title] 
                    action:@selector(openBookmarkAction:) 
                    keyEquivalent:shortCutKey];
            [menuItem setRepresentedObject:bookmark];
            [menuItem setImage:[bookmark icon]];
        }
        
        // Case of bookmark folder
        else {
            // Create menu item and submenu
            SRMenu* submenu;
            menuItem = [menu addItemWithTitle:[bookmark title] 
                    action:NULL 
                    keyEquivalent:@""];
            submenu = [[SRMenu alloc] initWithTitle:@""];
            [submenu autorelease];
            [submenu setRepresentedObject:bookmark];
            [submenu setDelegate:[menu delegate]];
            
            [menuItem setSubmenu:submenu];
            [menuItem setImage:[bookmark icon]];
        }
    }
    
    // Append open all in tabs
    [menu addItem:[NSMenuItem separatorItem]];
    menuItem = [menu addItemWithTitle:NSLocalizedString(@"Open in Tabs", nil) 
            action:@selector(openBookmarkInTabsAction:) 
            keyEquivalent:@""];
    [menuItem setRepresentedObject:bookmarks];
}

void _SRBookmarkFolderMenu(
        SRBookmark* bookmark, 
        NSMenu* menu, 
        int level)
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Check type and mutability
    if (![[bookmark isFolder] boolValue] || ![bookmark isMutable]) {
        return;
    }
    
    // Create menu item
    NSMenuItem* item;
    item = [[NSMenuItem alloc] initWithTitle:[bookmark title] 
            action:nil 
            keyEquivalent:@""];
    [item autorelease];
    [item setIndentationLevel:level];
    [item setRepresentedObject:bookmark];
    [item setImage:[bookmark icon]];
    
    // Add menu item
    [menu addItem:item];
    
    // Check children
    NSEnumerator*   enumerator;
    SRBookmark*     child;
    enumerator = [[bookmark sortedChildren] objectEnumerator];
    while (child = [enumerator nextObject]) {
        _SRBookmarkFolderMenu(child, menu, level + 1);
    }
}

NSMenu* SRBookmarkFolderMenu(
        SRBookmark* bookmark)
{
    // Create menu
    NSMenu* menu;
    menu = [[NSMenu alloc] initWithTitle:@""];
    [menu autorelease];
    
    // For root
    if ([[bookmark type] isEqualToString:@"Root"]) {
        NSEnumerator*   enumerator;
        SRBookmark*     child;
        enumerator = [[bookmark sortedChildren] objectEnumerator];
        while (child = [enumerator nextObject]) {
            _SRBookmarkFolderMenu(child, menu, 0);
        }
    }
    else {
        // Create folder menu
        _SRBookmarkFolderMenu(bookmark, menu, 0);
    }
    
    return menu;
}
