/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **************************************************************************
 */

#import "objc/TINKKeysetHandle.h"

#import "objc/TINKAead.h"
#import "objc/TINKKeyTemplate.h"
#import "objc/TINKKeysetReader.h"
#import "objc/aead/TINKAeadInternal.h"
#import "objc/core/TINKKeyTemplate_Internal.h"
#import "objc/core/TINKKeysetReader_Internal.h"
#import "objc/util/TINKErrors.h"
#import "objc/util/TINKStrings.h"

#include <iosfwd>
#include <iostream>
#include <sstream>
#include <string>

#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "tink/binary_keyset_reader.h"
#include "tink/binary_keyset_writer.h"
#include "tink/cleartext_keyset_handle.h"
#include "tink/keyset_handle.h"
#include "tink/util/status.h"
#include "proto/tink.pb.h"

static NSString *const kTinkService = @"com.google.crypto.tink";

@implementation TINKKeysetHandle {
  std::unique_ptr<crypto::tink::KeysetHandle> _ccKeysetHandle;
}

- (instancetype)initWithCCKeysetHandle:(std::unique_ptr<crypto::tink::KeysetHandle>)ccKeysetHandle {
  self = [super init];
  if (self) {
    _ccKeysetHandle = std::move(ccKeysetHandle);
  }
  return self;
}

- (void)dealloc {
  _ccKeysetHandle.reset();
}

- (instancetype)initWithNoSecretKeyset:(NSData *)keyset error:(NSError **)error {
  if (keyset == nil) {
    if (error) {
      *error = TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kInvalidArgument,
                                                            "keyset must be non-nil."));
    }
    return nil;
  }

  auto st = crypto::tink::KeysetHandle::ReadNoSecret(std::string(
      reinterpret_cast<const char *>(keyset.bytes), static_cast<size_t>(keyset.length)));
  if (!st.ok()) {
    if (error) {
      *error = TINKStatusToError(st.status());
      return nil;
    }
  }

  return [self initWithCCKeysetHandle:std::move(st.value())];
}

- (instancetype)initWithKeysetReader:(TINKKeysetReader *)reader
                              andKey:(id<TINKAead>)aeadKey
                               error:(NSError **)error {
  if (![aeadKey isKindOfClass:[TINKAeadInternal class]]) {
    if (error) {
      *error = TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kInvalidArgument,
                                                            "Invalid instance of TINKAead."));
    }
    return nil;
  }

  TINKAeadInternal *aead = aeadKey;
  crypto::tink::Aead *ccAead = [aead ccAead];
  if (!ccAead) {
    if (error) {
      *error = TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kInvalidArgument,
                                                            "Failed to get C++ Aead instance."));
    }
    return nil;
  }

  @synchronized(reader) {
    if (reader.used) {
      // A reader can only be used once.
      if (error) {
        *error = TINKStatusToError(
            crypto::tink::util::Status(absl::StatusCode::kResourceExhausted,
                                       "A KeysetReader can be used only once."));
      }
      return nil;
    }
    reader.used = YES;
  }
  auto st = crypto::tink::KeysetHandle::Read(reader.ccReader, *ccAead);
  if (!st.ok()) {
    if (error) {
      *error = TINKStatusToError(st.status());
      return nil;
    }
  }

  return [self initWithCCKeysetHandle:std::move(st.value())];
}

- (nullable instancetype)initFromKeychainWithName:(NSString *)keysetName error:(NSError **)error {
  return [self initFromKeychainWithName:keysetName accessGroup:nil error:error];
}

- (nullable instancetype)initFromKeychainWithName:(NSString *)keysetName
                                      accessGroup:(NSString *)accessGroup
                                            error:(NSError **)error {
  if (keysetName == nil) {
    if (error) {
      *error = TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kInvalidArgument,
                                                            "keysetName must be non-nil."));
    }
    return nil;
  }

  if (self = [super init]) {
    NSDictionary *getQuery = @{
      (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
      (__bridge id)kSecAttrAccount : keysetName,
      (__bridge id)kSecAttrService : kTinkService,
      (__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue,
    };

    if (accessGroup) {
      NSMutableDictionary *mutableGetQuery =
          [NSMutableDictionary dictionaryWithDictionary:getQuery];
      [mutableGetQuery setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup];
      getQuery = [mutableGetQuery copy];
    }

    absl::StatusCode errorCode = absl::StatusCode::kOk;
    std::string errorMessage = "";
    CFTypeRef dataTypeRef = NULL;
    OSStatus status = SecItemCopyMatching((CFDictionaryRef)getQuery, &dataTypeRef);
    switch (status) {
      case errSecSuccess:
        // Success, nothing to do.
        break;
      case errSecItemNotFound:
        errorMessage = "A keyset with the given name wasn't found in the keychain.";
        errorCode = absl::StatusCode::kNotFound;
        break;
      default:
        std::ostringstream oss;
        oss << "An error occurred while trying to retrieve the keyset from the keychain.";
        oss << " Error code: " << status;
        errorMessage = oss.str();
        errorCode = absl::StatusCode::kUnknown;
    }

    if (errorCode != absl::StatusCode::kOk) {
      if (error) {
        *error = TINKStatusToError(crypto::tink::util::Status(errorCode, errorMessage));
      }
      return nil;
    }

    NSData *keyset = (__bridge NSData *)dataTypeRef;
    auto reader = crypto::tink::BinaryKeysetReader::New(absl::string_view(
        reinterpret_cast<const char *>(keyset.bytes), static_cast<size_t>(keyset.length)));
    if (!reader.ok()) {
      if (error) {
        *error = TINKStatusToError(reader.status());
      }
      return nil;
    }

    auto read_result = crypto::tink::CleartextKeysetHandle::Read(std::move(reader.value()));
    if (!read_result.ok()) {
      if (error) {
        *error = TINKStatusToError(read_result.status());
        return nil;
      }
    }

    return [self initWithCCKeysetHandle:std::move(read_result.value())];
  }
  return nil;
}

+ (BOOL)deleteFromKeychainWithName:(NSString *)keysetName error:(NSError **)error {
  return [self deleteFromKeychainWithName:keysetName accessGroup:nil error:error];
}

+ (BOOL)deleteFromKeychainWithName:(NSString *)keysetName
                       accessGroup:(NSString *)accessGroup
                             error:(NSError **)error {
  if (keysetName == nil) {
    if (error) {
      *error = TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kInvalidArgument,
                                                            "keysetName must be non-nil."));
    }
    return NO;
  }

  NSDictionary *attributes = @{
    (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrAccount : keysetName,
    (__bridge id)kSecAttrService : kTinkService,
  };

  if (accessGroup) {
    NSMutableDictionary *mutableAttributes =
        [NSMutableDictionary dictionaryWithDictionary:attributes];
    [mutableAttributes setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup];
    attributes = [mutableAttributes copy];
  }

  OSStatus status = SecItemDelete((CFDictionaryRef)attributes);
  if (status != errSecSuccess && status != errSecItemNotFound) {
    if (error) {
      std::ostringstream oss;
      oss << "An error occurred while trying to delete the keyset from the keychain.";
      oss << " Keychain error code: " << status;
      std::string errorMessage = oss.str();
      *error =
          TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kUnknown, errorMessage));
    }
    return NO;
  }

  return YES;
}

- (BOOL)writeToKeychainWithName:(NSString *)keysetName
                      overwrite:(BOOL)overwrite
                          error:(NSError **)error {
  return [self writeToKeychainWithName:keysetName accessGroup:nil overwrite:overwrite error:error];
}

- (BOOL)writeToKeychainWithName:(NSString *)keysetName
                    accessGroup:(NSString *)accessGroup
                      overwrite:(BOOL)overwrite
                          error:(NSError **)error {
  if (keysetName == nil) {
    if (error) {
      *error = TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kInvalidArgument,
                                                            "keysetName must be non-nil."));
    }
    return NO;
  }

  auto keyset = crypto::tink::CleartextKeysetHandle::GetKeyset(*self.ccKeysetHandle);

  std::string serializedKeyset;
  if (!keyset.SerializeToString(&serializedKeyset)) {
    if (error) {
      *error = TINKStatusToError(crypto::tink::util::Status(
          absl::StatusCode::kInternal, "Could not serialize C++ KeyTemplate."));
    }
    return NO;
  }

  if (overwrite) {
    if (![TINKKeysetHandle deleteFromKeychainWithName:keysetName error:error]) {
      return NO;
    }
  }

  NSData *keysetData = TINKStringToNSData(serializedKeyset);
  NSDictionary *attributes = @{
    (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrAccount : keysetName,
    (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
    (__bridge id)kSecAttrService : kTinkService,
    (__bridge id)kSecAttrSynchronizable : (__bridge id)kCFBooleanFalse,
    (__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue,
    (__bridge id)kSecValueData : keysetData,
  };

  if (accessGroup) {
    NSMutableDictionary *mutableAttributes =
        [NSMutableDictionary dictionaryWithDictionary:attributes];
    [mutableAttributes setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup];
    attributes = [mutableAttributes copy];
  }

  OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
  switch (status) {
    case errSecSuccess:
      return YES;
    case errSecDuplicateItem:
      if (error) {
        std::ostringstream oss;
        oss << "A keyset with the same keysetName already exists in the keychain.";
        oss << " Please delete it and try again. Keychain error code: " << status;
        std::string errorMessage = oss.str();
        *error =
            TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kUnknown, errorMessage));
      }
      return NO;
    default:
      if (error) {
        std::ostringstream oss;
        oss << "An error occurred while trying to store the keyset in the keychain.";
        oss << " Error code: " << status;
        std::string errorMessage = oss.str();
        *error =
            TINKStatusToError(crypto::tink::util::Status(absl::StatusCode::kUnknown, errorMessage));
      }
      return NO;
  }
}

- (instancetype)initWithKeyTemplate:(TINKKeyTemplate *)keyTemplate error:(NSError **)error {
  auto st = crypto::tink::KeysetHandle::GenerateNew(*(keyTemplate.ccKeyTemplate));
  if (!st.ok()) {
    if (error) {
      *error = TINKStatusToError(st.status());
    }
    return nil;
  }

  return [self initWithCCKeysetHandle:std::move(st.value())];
}

- (crypto::tink::KeysetHandle *)ccKeysetHandle {
  return _ccKeysetHandle.get();
}

- (void)setCcKeysetHandle:(std::unique_ptr<crypto::tink::KeysetHandle>)handle {
  _ccKeysetHandle = std::move(handle);
}

+ (nullable instancetype)publicKeysetHandleWithHandle:(TINKKeysetHandle *)aHandle
                                                error:(NSError **)error {
  crypto::tink::KeysetHandle *ccKeysetHandle = aHandle.ccKeysetHandle;
  auto status = ccKeysetHandle->GetPublicKeysetHandle();
  if (!status.ok()) {
    if (error) {
      *error = TINKStatusToError(status.status());
    }
    return nil;
  }
  return [[TINKKeysetHandle alloc] initWithCCKeysetHandle:std::move(status.value())];
}

- (NSData *)serializedKeysetNoSecret:(NSError **)error {
  std::stringbuf buffer;
  auto writerResult = crypto::tink::BinaryKeysetWriter::New(
      absl::make_unique<std::ostream>(&buffer));
  if (!writerResult.ok()) {
    if (error) {
      *error = TINKStatusToError(writerResult.status());
    }
    return nil;
  }
  auto writer = std::move(writerResult.value());
  auto writeNoSecretStatus = self.ccKeysetHandle->WriteNoSecret(writer.get());
  if (!writeNoSecretStatus.ok()) {
    if (error) {
      *error = TINKStatusToError(writeNoSecretStatus);
    }
    return nil;
  }
  return TINKStringToNSData(buffer.str());
}

@end
