/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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.
 */

package com.android.server.accounts;

import android.accounts.Account;
import android.util.LruCache;
import android.util.Pair;

import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * TokenCaches manage time limited authentication tokens in memory. 
 */
/* default */ class TokenCache {

    private static final int MAX_CACHE_CHARS = 64000;

    private static class Value {
        public final String token;
        public final long expiryEpochMillis;

        public Value(String token, long expiryEpochMillis) {
            this.token = token;
            this.expiryEpochMillis = expiryEpochMillis;
        }
    }

    private static class Key {
        public final Account account;
        public final String packageName;
        public final String tokenType;
        public final byte[] sigDigest;

        public Key(Account account, String tokenType, String packageName, byte[] sigDigest) {
            this.account = account;
            this.tokenType = tokenType;
            this.packageName = packageName;
            this.sigDigest = sigDigest;
        }

        @Override
        public boolean equals(Object o) {
            if (o != null && o instanceof Key) {
                Key cacheKey = (Key) o;
                return Objects.equals(account, cacheKey.account)
                        && Objects.equals(packageName, cacheKey.packageName)
                        && Objects.equals(tokenType, cacheKey.tokenType)
                        && Arrays.equals(sigDigest, cacheKey.sigDigest);
            } else {
                return false;
            }
        }

        @Override
        public int hashCode() {
            return account.hashCode()
                    ^ packageName.hashCode()
                    ^ tokenType.hashCode()
                    ^ Arrays.hashCode(sigDigest);
        }
    }

    private static class TokenLruCache extends LruCache<Key, Value> {

        private class Evictor {
            private final List<Key> mKeys;

            public Evictor() {
                mKeys = new ArrayList<>();
            }

            public void add(Key k) {
                mKeys.add(k);
            }

            public void evict() {
                for (Key k : mKeys) {
                    TokenLruCache.this.remove(k);
                }
            }
        }

        /**
         * Map associated tokens with an Evictor that will manage evicting the token from the
         * cache. This reverse lookup is needed because very little information is given at token
         * invalidation time.
         */
        private HashMap<Pair<String, String>, Evictor> mTokenEvictors = new HashMap<>();
        private HashMap<Account, Evictor> mAccountEvictors = new HashMap<>();

        public TokenLruCache() {
            super(MAX_CACHE_CHARS);
        }

        @Override
        protected int sizeOf(Key k, Value v) {
            return v.token.length();
        }

        @Override
        protected void entryRemoved(boolean evicted, Key k, Value oldVal, Value newVal) {
            // When a token has been removed, clean up the associated Evictor.
            if (oldVal != null && newVal == null) {
                /*
                 * This is recursive, but it won't spiral out of control because LruCache is
                 * thread safe and the Evictor can only be removed once.
                 */
                Evictor evictor = mTokenEvictors.remove(new Pair<>(k.account.type, oldVal.token));
                if (evictor != null) {
                    evictor.evict();
                }
            }
        }

        public void putToken(Key k, Value v) {
            // Prepare for removal by token string.
            Pair<String, String> mapKey = new Pair<>(k.account.type, v.token);
            Evictor tokenEvictor = mTokenEvictors.get(mapKey);
            if (tokenEvictor == null) {
                tokenEvictor = new Evictor();
            }
            tokenEvictor.add(k);
            mTokenEvictors.put(mapKey, tokenEvictor);

            // Prepare for removal by associated account.
            Evictor accountEvictor = mAccountEvictors.get(k.account);
            if (accountEvictor == null) {
                accountEvictor = new Evictor();
            }
            accountEvictor.add(k);
            mAccountEvictors.put(k.account, tokenEvictor);

            // Only cache the token once we can remove it directly or by account.
            put(k, v);
        }

        public void evict(String accountType, String token) {
            Evictor evictor = mTokenEvictors.get(new Pair<>(accountType, token));
            if (evictor != null) {
                evictor.evict();
            }
            
        }

        public void evict(Account account) {
            Evictor evictor = mAccountEvictors.get(account);
            if (evictor != null) {
                evictor.evict();
            }
        }
    }

    /**
     * Map associating basic token lookup information with with actual tokens (and optionally their
     * expiration times). 
     */
    private TokenLruCache mCachedTokens = new TokenLruCache();

    /**
     * Caches the specified token until the specified expiryMillis. The token will be associated
     * with the given token type, package name, and digest of signatures.
     *
     * @param token
     * @param tokenType
     * @param packageName
     * @param sigDigest
     * @param expiryMillis
     */
    public void put(
            Account account,
            String token,
            String tokenType,
            String packageName,
            byte[] sigDigest,
            long expiryMillis) {
        Objects.requireNonNull(account);
        if (token == null || System.currentTimeMillis() > expiryMillis) {
            return;
        }
        Key k = new Key(account, tokenType, packageName, sigDigest);
        Value v = new Value(token, expiryMillis);
        mCachedTokens.putToken(k, v);
    }

    /**
     * Evicts the specified token from the cache. This should be called as part of a token
     * invalidation workflow.
     */
    public void remove(String accountType, String token) {
        mCachedTokens.evict(accountType, token);
    }

    public void remove(Account account) {
        mCachedTokens.evict(account);
    }

    /**
     * Gets a token from the cache if possible.
     */
    public String get(Account account, String tokenType, String packageName, byte[] sigDigest) {
        Key k = new Key(account, tokenType, packageName, sigDigest);
        Value v = mCachedTokens.get(k);
        long currentTime = System.currentTimeMillis();
        if (v != null && currentTime < v.expiryEpochMillis) {
            return v.token;
        } else if (v != null) {
            remove(account.type, v.token);
        }
        return null;
    }
}
