--[[----------------------------------------------------------------------------

KSKeychainService.lua

--------------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2011 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remain the property of
Adobe Systems Incorporated and its suppliers, if any. The intellectual and
technical concepts contained herein are proprietary to Adobe Systems
Incorporated and its suppliers and may be covered by U.S. and Foreign
Patents, patents in process, and are protected by trade secret or copyright
law.  Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

--------------------------------------------------------------------------------

This namespace provides secure storage for passwords, access tokens, and similar
information that is especially important to the application. It may be accessed
from any thread.

This API is a minimalist wrapper over Mac and iOS Keychain Services.

------------------------------------------------------------------------------]]

	-- WF.core.logging
local WFLogger = require 'WFLogger'

	-- WF.core.rxlua
local WFRxRunUntilDone = require 'WFRxRunUntilDone'

	-- WF.core.threading
local WFWorkerThread = require 'WFWorkerThread'

	-- WF.core.utils
local WFArguments = require 'WFArguments'


--------------------------------------------------------------------------------

local check = assert( WFArguments.check )

local runUntilDone = WFRxRunUntilDone

local keychainManagerImp = WFWorkerThread( 'KSKeychainServiceImp.lua' )

local logger = WFLogger "KSKeychainService"
--	:setLevel( 'debug' )


--============================================================================--

-- @mark KSKeychainService namespace

--------------------------------------------------------------------------------
--[[!
	\class KSKeychainService

	\brief This namespace provides secure storage for passwords, access tokens,
		and similar information. It can be accessed from any thread.
]]--

local KSKeychainService = {}

--------------------------------------------------------------------------------
--[[!
	Reads a single value from the keychain.

	\param key (string) The key for the desired value.

	\return An Observable object that resolves to the value.
]]--

function KSKeychainService.read( key )

	check( '+string' )

	return keychainManagerImp:request( 'read', key )
		:tap( function( value )
			logger:debugf( "read key %s => value %s", key, value )
		end )

end

--------------------------------------------------------------------------------
--[[!
	Reads a single value from the keychain.

	\param key (string) The key for the desired value.

	\return A promise object that resolves to the value.
]]--

function KSKeychainService.readP( key )

	check( '+string' )

	return keychainManagerImp:requestP( 'read', key )
		:observeP( function( _, value )
			logger:debugf( "readP key %s => value %s", key, value )
		end )

end

--------------------------------------------------------------------------------
--[[!
	Writes a single value into the keychain.

	\param key (string) The key for the new value.
	\param value (string) The new value.

	\return An Observable object that signals completion. This can be ignored.
]]--

function KSKeychainService.write( key, value )

	check( '+string', '+string' )

	return keychainManagerImp:request( 'write', key, value )
		:tapOnCompleted( function()
			logger:debugf( "write key %s => value %s", key, value )
		end )
		:call( runUntilDone )

end

--------------------------------------------------------------------------------
--[[!
	Writes a single value into the keychain.

	\param key (string) The key for the new value.
	\param value (string) The new value.

	\return A promise object that signals completion. This can be ignored.
]]--

function KSKeychainService.writeP( key, value )

	check( '+string', '+string' )

	return keychainManagerImp:requestP( 'write', key, value )
		:observeP( function()
			logger:debugf( "writeP key %s => value %s", key, value )
		end )
		:runUntilDoneP()

end

--------------------------------------------------------------------------------
--[[!
	Deletes a value from the keychain.

	\param key (string) The key for the valuet to delete.

	\return An Observable object that signals completion, This can be ignored.
]]--

function KSKeychainService.delete( key )

	check( '+string' )

	return keychainManagerImp:request( 'delete', key )
		:tapOnCompleted( function()
			logger:debugf( "delete key %s", key)
		end )
		:call( runUntilDone )

end

--------------------------------------------------------------------------------
--[[!
	Deletes a value from the keychain.

	\param key (string) The key for the valuet to delete.

	\return A promise object that signals completion, This can be ignored.
]]--

function KSKeychainService.deleteP( key )

	check( '+string' )

	return keychainManagerImp:requestP( 'delete', key )
		:observeP( function()
			logger:debugf( "deleteP key %s", key)
		end )
		:runUntilDoneP()

end

--------------------------------------------------------------------------------

return KSKeychainService
