// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "rlz/mac/lib/rlz_value_store_mac.h"

#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/strings/sys_string_conversions.h"
#include "rlz/lib/assert.h"
#include "rlz/lib/lib_values.h"
#include "rlz/lib/recursive_cross_process_lock_posix.h"
#include "rlz/lib/rlz_lib.h"

#import <Foundation/Foundation.h>
#include <pthread.h>

using base::mac::ObjCCast;

namespace rlz_lib {

// These are written to disk and should not be changed.
NSString* const kPingTimeKey = @"pingTime";
NSString* const kAccessPointKey = @"accessPoints";
NSString* const kProductEventKey = @"productEvents";
NSString* const kStatefulEventKey = @"statefulEvents";

namespace {

NSString* GetNSProductName(Product product) {
  return base::SysUTF8ToNSString(GetProductName(product));
}

NSString* GetNSAccessPointName(AccessPoint p) {
  return base::SysUTF8ToNSString(GetAccessPointName(p));
}

// Retrieves a subdictionary in |p| for key |k|, creating it if necessary.
// If the dictionary contains an object for |k| that is not a mutable
// dictionary, that object is replaced with an empty mutable dictinary.
NSMutableDictionary* GetOrCreateDict(
    NSMutableDictionary* p, NSString* k) {
  NSMutableDictionary* d = ObjCCast<NSMutableDictionary>([p objectForKey:k]);
  if (!d) {
    d = [NSMutableDictionary dictionaryWithCapacity:0];
    [p setObject:d forKey:k];
  }
  return d;
}

}  // namespace

RlzValueStoreMac::RlzValueStoreMac(NSMutableDictionary* dict,
                                   NSString* plist_path)
  : dict_([dict retain]), plist_path_([plist_path retain]) {
}

RlzValueStoreMac::~RlzValueStoreMac() {
}

bool RlzValueStoreMac::HasAccess(AccessType type) {
  NSFileManager* manager = [NSFileManager defaultManager];
  switch (type) {
    case kReadAccess:  return [manager isReadableFileAtPath:plist_path_];
    case kWriteAccess: return [manager isWritableFileAtPath:plist_path_];
  }
}

bool RlzValueStoreMac::WritePingTime(Product product, int64_t time) {
  NSNumber* n = [NSNumber numberWithLongLong:time];
  [ProductDict(product) setObject:n forKey:kPingTimeKey];
  return true;
}

bool RlzValueStoreMac::ReadPingTime(Product product, int64_t* time) {
  if (NSNumber* n =
      ObjCCast<NSNumber>([ProductDict(product) objectForKey:kPingTimeKey])) {
    *time = [n longLongValue];
    return true;
  }
  return false;
}

bool RlzValueStoreMac::ClearPingTime(Product product) {
  [ProductDict(product) removeObjectForKey:kPingTimeKey];
  return true;
}


bool RlzValueStoreMac::WriteAccessPointRlz(AccessPoint access_point,
                                           const char* new_rlz) {
  NSMutableDictionary* d = GetOrCreateDict(WorkingDict(), kAccessPointKey);
  [d setObject:base::SysUTF8ToNSString(new_rlz)
      forKey:GetNSAccessPointName(access_point)];
  return true;
}

bool RlzValueStoreMac::ReadAccessPointRlz(AccessPoint access_point,
                                          char* rlz,
                                          size_t rlz_size) {
  // Reading a non-existent access point counts as success.
  if (NSDictionary* d = ObjCCast<NSDictionary>(
        [WorkingDict() objectForKey:kAccessPointKey])) {
    NSString* val = ObjCCast<NSString>(
        [d objectForKey:GetNSAccessPointName(access_point)]);
    if (!val) {
      if (rlz_size > 0)
        rlz[0] = '\0';
      return true;
    }

    std::string s = base::SysNSStringToUTF8(val);
    if (s.size() >= rlz_size) {
      rlz[0] = 0;
      ASSERT_STRING("GetAccessPointRlz: Insufficient buffer size");
      return false;
    }
    strncpy(rlz, s.c_str(), rlz_size);
    return true;
  }
  if (rlz_size > 0)
    rlz[0] = '\0';
  return true;
}

bool RlzValueStoreMac::ClearAccessPointRlz(AccessPoint access_point) {
  if (NSMutableDictionary* d = ObjCCast<NSMutableDictionary>(
      [WorkingDict() objectForKey:kAccessPointKey])) {
    [d removeObjectForKey:GetNSAccessPointName(access_point)];
  }
  return true;
}


bool RlzValueStoreMac::AddProductEvent(Product product,
                                       const char* event_rlz) {
  [GetOrCreateDict(ProductDict(product), kProductEventKey)
      setObject:[NSNumber numberWithBool:YES]
      forKey:base::SysUTF8ToNSString(event_rlz)];
  return true;
}

bool RlzValueStoreMac::ReadProductEvents(Product product,
                                         std::vector<std::string>* events) {
  if (NSDictionary* d = ObjCCast<NSDictionary>(
      [ProductDict(product) objectForKey:kProductEventKey])) {
    for (NSString* s in d)
      events->push_back(base::SysNSStringToUTF8(s));
    return true;
  }
  return true;
}

bool RlzValueStoreMac::ClearProductEvent(Product product,
                                         const char* event_rlz) {
  if (NSMutableDictionary* d = ObjCCast<NSMutableDictionary>(
      [ProductDict(product) objectForKey:kProductEventKey])) {
    [d removeObjectForKey:base::SysUTF8ToNSString(event_rlz)];
    return true;
  }
  return false;
}

bool RlzValueStoreMac::ClearAllProductEvents(Product product) {
  [ProductDict(product) removeObjectForKey:kProductEventKey];
  return true;
}


bool RlzValueStoreMac::AddStatefulEvent(Product product,
                                        const char* event_rlz) {
  [GetOrCreateDict(ProductDict(product), kStatefulEventKey)
      setObject:[NSNumber numberWithBool:YES]
      forKey:base::SysUTF8ToNSString(event_rlz)];
  return true;
}

bool RlzValueStoreMac::IsStatefulEvent(Product product,
                                       const char* event_rlz) {
  if (NSDictionary* d = ObjCCast<NSDictionary>(
        [ProductDict(product) objectForKey:kStatefulEventKey])) {
    return [d objectForKey:base::SysUTF8ToNSString(event_rlz)] != nil;
  }
  return false;
}

bool RlzValueStoreMac::ClearAllStatefulEvents(Product product) {
  [ProductDict(product) removeObjectForKey:kStatefulEventKey];
  return true;
}


void RlzValueStoreMac::CollectGarbage() {
  NOTIMPLEMENTED();
}

NSDictionary* RlzValueStoreMac::dictionary() {
  return dict_.get();
}

NSMutableDictionary* RlzValueStoreMac::WorkingDict() {
  std::string brand(SupplementaryBranding::GetBrand());
  if (brand.empty())
    return dict_;

  NSString* brand_ns =
      [@"brand_" stringByAppendingString:base::SysUTF8ToNSString(brand)];

  return GetOrCreateDict(dict_.get(), brand_ns);
}

NSMutableDictionary* RlzValueStoreMac::ProductDict(Product p) {
  return GetOrCreateDict(WorkingDict(), GetNSProductName(p));
}


namespace {

RecursiveCrossProcessLock g_recursive_lock =
    RECURSIVE_CROSS_PROCESS_LOCK_INITIALIZER;

// This is set during test execution, to write RLZ files into a temporary
// directory instead of the user's Application Support folder.
NSString* g_test_folder;

// RlzValueStoreMac keeps its data in memory and only writes it to disk when
// ScopedRlzValueStoreLock goes out of scope. Hence, if several
// ScopedRlzValueStoreLocks are nested, they all need to use the same store
// object.

// This counts the nesting depth.
int g_lock_depth = 0;

// This is the store object that might be shared. Only set if g_lock_depth > 0.
RlzValueStoreMac* g_store_object = NULL;


NSString* CreateRlzDirectory() {
  NSFileManager* manager = [NSFileManager defaultManager];
  NSArray* paths = NSSearchPathForDirectoriesInDomains(
      NSApplicationSupportDirectory, NSUserDomainMask, /*expandTilde=*/YES);
  NSString* folder = nil;
  if ([paths count] > 0)
    folder = ObjCCast<NSString>([paths objectAtIndex:0]);
  if (!folder)
    folder = [@"~/Library/Application Support" stringByStandardizingPath];
  folder = [folder stringByAppendingPathComponent:@"Google/RLZ"];

  if (g_test_folder)
    folder = [g_test_folder stringByAppendingPathComponent:folder];

  [manager createDirectoryAtPath:folder
     withIntermediateDirectories:YES
                      attributes:nil
                           error:nil];
  return folder;
}

// Returns the path of the rlz plist store, also creates the parent directory
// path if it doesn't exist.
NSString* RlzPlistFilename() {
  NSString* const kRlzFile = @"RlzStore.plist";
  return [CreateRlzDirectory() stringByAppendingPathComponent:kRlzFile];
}

// Returns the path of the rlz lock file, also creates the parent directory
// path if it doesn't exist.
NSString* RlzLockFilename() {
  NSString* const kRlzLockfile = @"flockfile";
  return [CreateRlzDirectory() stringByAppendingPathComponent:kRlzLockfile];
}

}  // namespace

ScopedRlzValueStoreLock::ScopedRlzValueStoreLock() {
  bool got_distributed_lock = g_recursive_lock.TryGetCrossProcessLock(
      base::FilePath([RlzLockFilename() fileSystemRepresentation]));
  // At this point, we hold the in-process lock, no matter the value of
  // |got_distributed_lock|.

  ++g_lock_depth;

  if (!got_distributed_lock) {
    // Give up. |store_| isn't set, which signals to callers that acquiring
    // the lock failed. |g_recursive_lock| will be released by the
    // destructor.
    CHECK(!g_store_object);
    return;
  }

  if (g_lock_depth > 1) {
    // Reuse the already existing store object. Note that it can be NULL when
    // lock acquisition succeeded but the rlz data file couldn't be read.
    store_.reset(g_store_object);
    return;
  }

  CHECK(!g_store_object);

  NSString* plist = RlzPlistFilename();

  // Create an empty file if none exists yet.
  NSFileManager* manager = [NSFileManager defaultManager];
  if (![manager fileExistsAtPath:plist isDirectory:NULL])
    [[NSDictionary dictionary] writeToFile:plist atomically:YES];

  NSMutableDictionary* dict =
      [NSMutableDictionary dictionaryWithContentsOfFile:plist];
  VERIFY(dict);

  if (dict) {
    store_.reset(new RlzValueStoreMac(dict, plist));
    g_store_object = (RlzValueStoreMac*)store_.get();
  }
}

ScopedRlzValueStoreLock::~ScopedRlzValueStoreLock() {
  --g_lock_depth;
  CHECK(g_lock_depth >= 0);

  if (g_lock_depth > 0) {
    // Other locks are still using store_, don't free it yet.
    ignore_result(store_.release());
    return;
  }

  if (store_.get()) {
    g_store_object = NULL;

    NSDictionary* dict =
        static_cast<RlzValueStoreMac*>(store_.get())->dictionary();
    VERIFY([dict writeToFile:RlzPlistFilename() atomically:YES]);
  }

  // Check that "store_ set" => "file_lock acquired". The converse isn't true,
  // for example if the rlz data file can't be read.
  if (store_.get())
    CHECK(g_recursive_lock.file_lock_ != -1);
  if (g_recursive_lock.file_lock_ == -1)
    CHECK(!store_.get());

  g_recursive_lock.ReleaseLock();
}

RlzValueStore* ScopedRlzValueStoreLock::GetStore() {
  return store_.get();
}

namespace testing {

void SetRlzStoreDirectory(const base::FilePath& directory) {
  base::mac::ScopedNSAutoreleasePool pool;

  [g_test_folder release];
  if (directory.empty()) {
    g_test_folder = nil;
  } else {
    // Not Unsafe on OS X.
    g_test_folder =
      [[NSString alloc] initWithUTF8String:directory.AsUTF8Unsafe().c_str()];
  }
}

std::string RlzStoreFilenameStr() {
  @autoreleasepool {
    return std::string([RlzPlistFilename() fileSystemRepresentation]);
  }
}

}  // namespace testing

}  // namespace rlz_lib
