/*
 * Copyright (C) 2015 Apple Inc. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 "config.h"
#import "SearchPopupMenuCocoa.h"

#import <wtf/cocoa/VectorCocoa.h>

namespace WebCore {

static NSString * const dateKey = @"date";
static NSString * const itemsKey = @"items";
static NSString * const searchesKey = @"searches";
static NSString * const searchStringKey = @"searchString";

static NSString *searchFieldRecentSearchesStorageDirectory()
{
    NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
    if (!appName)
        appName = [[NSProcessInfo processInfo] processName];
    
    return [[NSHomeDirectory() stringByAppendingPathComponent:@"Library/WebKit"] stringByAppendingPathComponent:appName];
}

static NSString *searchFieldRecentSearchesPlistPath()
{
    return [searchFieldRecentSearchesStorageDirectory() stringByAppendingPathComponent:@"RecentSearches.plist"];
}

static RetainPtr<NSMutableDictionary> readSearchFieldRecentSearchesPlist()
{
    return adoptNS([[NSMutableDictionary alloc] initWithContentsOfFile:searchFieldRecentSearchesPlistPath()]);
}

static WallTime toSystemClockTime(NSDate *date)
{
    ASSERT(date);
    return WallTime::fromRawSeconds(date.timeIntervalSince1970);
}

static NSDate *toNSDateFromSystemClock(WallTime time)
{
    return [NSDate dateWithTimeIntervalSince1970:time.secondsSinceEpoch().seconds()];
}

static NSMutableArray *typeCheckedRecentSearchesArray(NSMutableDictionary *itemsDictionary, NSString *name)
{
    NSMutableDictionary *nameDictionary = [itemsDictionary objectForKey:name];
    if (![nameDictionary isKindOfClass:[NSDictionary class]])
        return nil;

    NSMutableArray *recentSearches = [nameDictionary objectForKey:searchesKey];
    if (![recentSearches isKindOfClass:[NSArray class]])
        return nil;

    return recentSearches;
}

static NSDate *typeCheckedDateInRecentSearch(NSDictionary *recentSearch)
{
    if (![recentSearch isKindOfClass:[NSDictionary class]])
        return nil;

    NSDate *date = [recentSearch objectForKey:dateKey];
    if (![date isKindOfClass:[NSDate class]])
        return nil;

    return date;
}

static RetainPtr<NSDictionary> typeCheckedRecentSearchesRemovingRecentSearchesAddedAfterDate(NSDate *date)
{
    if ([date isEqualToDate:[NSDate distantPast]])
        return nil;

    RetainPtr<NSMutableDictionary> recentSearchesPlist = readSearchFieldRecentSearchesPlist();
    NSMutableDictionary *itemsDictionary = [recentSearchesPlist objectForKey:itemsKey];
    if (![itemsDictionary isKindOfClass:[NSDictionary class]])
        return nil;

    RetainPtr<NSMutableArray> keysToRemove = adoptNS([[NSMutableArray alloc] init]);
    for (NSString *key in itemsDictionary) {
        if (![key isKindOfClass:[NSString class]])
            return nil;

        NSMutableArray *recentSearches = typeCheckedRecentSearchesArray(itemsDictionary, key);
        if (!recentSearches)
            return nil;

        RetainPtr<NSMutableArray> entriesToRemove = adoptNS([[NSMutableArray alloc] init]);
        for (NSDictionary *recentSearch in recentSearches) {
            NSDate *dateAdded = typeCheckedDateInRecentSearch(recentSearch);
            if (!dateAdded)
                return nil;

            if ([dateAdded compare:date] == NSOrderedDescending)
                [entriesToRemove addObject:recentSearch];
        }

        [recentSearches removeObjectsInArray:entriesToRemove.get()];
        if (!recentSearches.count)
            [keysToRemove addObject:key];
    }

    [itemsDictionary removeObjectsForKeys:keysToRemove.get()];
    if (!itemsDictionary.count)
        return nil;

    return recentSearchesPlist;
}

static void writeEmptyRecentSearchesPlist()
{
    auto emptyItemsDictionary = adoptNS([[NSDictionary alloc] init]);
    auto emptyRecentSearchesDictionary = adoptNS([[NSDictionary alloc] initWithObjectsAndKeys:emptyItemsDictionary.get(), itemsKey, nil]);
    [emptyRecentSearchesDictionary writeToFile:searchFieldRecentSearchesPlistPath() atomically:YES];
}

void saveRecentSearches(const String& name, const Vector<RecentSearch>& searchItems)
{
    if (name.isEmpty())
        return;

    RetainPtr<NSDictionary> recentSearchesPlist = readSearchFieldRecentSearchesPlist();
    RetainPtr<NSMutableDictionary> itemsDictionary = [recentSearchesPlist objectForKey:itemsKey];

    // The NSMutableDictionary method we use to read the property list guarantees we get only
    // mutable containers, but it does not guarantee the file has a dictionary as expected.
    if (![itemsDictionary isKindOfClass:[NSDictionary class]]) {
        itemsDictionary = adoptNS([[NSMutableDictionary alloc] init]);
        recentSearchesPlist = adoptNS([[NSDictionary alloc] initWithObjectsAndKeys:itemsDictionary.get(), itemsKey, nil]);
    }

    if (searchItems.isEmpty())
        [itemsDictionary removeObjectForKey:name];
    else {
        auto items = createNSArray(searchItems, [] (auto& item) {
            return adoptNS([[NSDictionary alloc] initWithObjectsAndKeys:item.string, searchStringKey, toNSDateFromSystemClock(item.time), dateKey, nil]);
        });
        [itemsDictionary setObject:adoptNS([[NSDictionary alloc] initWithObjectsAndKeys:items.get(), searchesKey, nil]).get() forKey:name];
    }

    [recentSearchesPlist writeToFile:searchFieldRecentSearchesPlistPath() atomically:YES];
}

Vector<RecentSearch> loadRecentSearches(const String& name)
{
    Vector<RecentSearch> searchItems;

    if (name.isEmpty())
        return searchItems;

    RetainPtr<NSMutableDictionary> recentSearchesPlist = readSearchFieldRecentSearchesPlist();
    if (!recentSearchesPlist)
        return searchItems;

    NSMutableDictionary *items = [recentSearchesPlist objectForKey:itemsKey];
    if (![items isKindOfClass:[NSDictionary class]])
        return searchItems;

    NSArray *recentSearches = typeCheckedRecentSearchesArray(items, name);
    if (!recentSearches)
        return searchItems;
    
    for (NSDictionary *item in recentSearches) {
        NSDate *date = typeCheckedDateInRecentSearch(item);
        if (!date)
            continue;

        NSString *searchString = [item objectForKey:searchStringKey];
        if (![searchString isKindOfClass:[NSString class]])
            continue;
        
        searchItems.append({ String{ searchString }, toSystemClockTime(date) });
    }

    return searchItems;
}

void removeRecentlyModifiedRecentSearches(WallTime oldestTimeToRemove)
{
    NSDate *date = toNSDateFromSystemClock(oldestTimeToRemove);
    auto recentSearchesPlist = typeCheckedRecentSearchesRemovingRecentSearchesAddedAfterDate(date);
    if (recentSearchesPlist)
        [recentSearchesPlist writeToFile:searchFieldRecentSearchesPlistPath() atomically:YES];
    else
        writeEmptyRecentSearchesPlist();
}

}
