package ru.yandex.wmtools.common.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;

import ru.yandex.common.framework.user.UserInfo;
import ru.yandex.common.util.cache.ObjectProvider;
import ru.yandex.common.util.cache.SimpleCache;

/**
 * @author avhaliullin
 */
public class WMBlackBoxUserService implements UserService {
    private static final Logger log = LoggerFactory.getLogger(WMBlackBoxUserService.class);
    private UserService uncachedUserService;

    private ObjectProvider<Long, SimpleReference<UserInfo>> userInfoObjectProvider = new ObjectProvider<Long, SimpleReference<UserInfo>>() {
        @Override
        public SimpleReference<UserInfo> getData(Long key) {
            return actuallyGetUserInfo(key);
        }
    };
    private SimpleCache<Long, SimpleReference<UserInfo>> userInfoCache =
            new SimpleCache<Long, SimpleReference<UserInfo>>(userInfoObjectProvider);

    private ObjectProvider<String, SimpleReference<Long>> userIdObjectProvider = new ObjectProvider<String, SimpleReference<Long>>() {
        @Override
        public SimpleReference<Long> getData(String key) {
            return actuallyGetUidByLogin(key);
        }
    };
    private SimpleCache<String, SimpleReference<Long>> userIdCache =
            new SimpleCache<String, SimpleReference<Long>>(userIdObjectProvider);

    private SimpleReference<UserInfo> actuallyGetUserInfo(long uid) {
        return new SimpleReference<UserInfo>(uncachedUserService.getUserInfo(uid));
    }

    private SimpleReference<Long> actuallyGetUidByLogin(String login) {
        return new SimpleReference<Long>(uncachedUserService.getUidByLogin(login));
    }

    @Override
    public UserInfo getUserInfo(long uid) {
        return userInfoCache.getData(uid).getValue();
    }

    @Override
    public Long getUidByLogin(String login) {
        return userIdCache.getData(login).getValue();
    }

    private class SimpleReference<T> {
        private final T value;

        public SimpleReference(T value) {
            this.value = value;
        }

        public T getValue() {
            return value;
        }
    }

    @Required
    public void setUncachedUserService(UserService uncachedUserService) {
        this.uncachedUserService = uncachedUserService;
    }

    public void setActualTimeInSeconds(long actualTimeInSeconds) {
        userInfoCache.setActualTimeInSeconds(actualTimeInSeconds);
        userIdCache.setActualTimeInSeconds(actualTimeInSeconds);
    }
}
