package app

const appCredentialStorageScheme = CredentialStorageScheme

func (store *Store) hasAppCredentialStorage() bool {
	return HasCredentialStorage(store.appCredentialStorageKey)
}

func (store *Store) appCredentialDecryptionKeys() [][]byte {
	return credentialStorageKeyCandidates(store.appCredentialStorageKey, store.legacyAppCredentialStorageKeys)
}

func (store *Store) marshalAppCredentialsObject(value map[string]any) ([]byte, error) {
	return MarshalCredentialsObject(store.appCredentialStorageKey, value)
}

func (store *Store) encryptStoredAppCredentialsJSON(plaintextJSON []byte) ([]byte, error) {
	return EncryptStoredCredentialsJSON(store.appCredentialStorageKey, plaintextJSON)
}

func (store *Store) decryptStoredAppCredentialsJSON(storedJSON []byte) ([]byte, error) {
	return DecryptStoredCredentialsJSONWithFallback(store.appCredentialStorageKey, store.legacyAppCredentialStorageKeys, storedJSON)
}

func normalizeStoredAppCredentialsJSON(payload []byte) ([]byte, error) {
	return NormalizeStoredCredentialsJSON(payload)
}

func jsonObjectIsEmpty(payload []byte) bool {
	return JSONObjectIsEmpty(payload)
}

func encryptAppCredential(key []byte, plaintext string) (string, error) {
	return EncryptCredential(key, plaintext)
}

func decryptAppCredential(key []byte, ciphertext string) (string, error) {
	return DecryptCredential(key, ciphertext)
}

func cloneCredentialStorageKeys(keys [][]byte) [][]byte {
	if len(keys) == 0 {
		return nil
	}
	cloned := make([][]byte, 0, len(keys))
	for _, key := range keys {
		if len(key) == 0 {
			continue
		}
		cloned = append(cloned, append([]byte(nil), key...))
	}
	return cloned
}

func credentialStorageKeyCandidates(primary []byte, legacy [][]byte) [][]byte {
	candidates := make([][]byte, 0, 1+len(legacy))
	if len(primary) > 0 {
		candidates = append(candidates, primary)
	}
	for _, key := range legacy {
		if len(key) == 0 || credentialStorageKeySeen(candidates, key) {
			continue
		}
		candidates = append(candidates, key)
	}
	return candidates
}

func credentialStorageKeySeen(keys [][]byte, candidate []byte) bool {
	for _, key := range keys {
		if string(key) == string(candidate) {
			return true
		}
	}
	return false
}
