package me.qwq.doghouse.component;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.sqids.Sqids;

import lombok.extern.slf4j.Slf4j;
import me.qwq.doghouse.entity.config.SiteConfig;
import me.qwq.doghouse.util.Cryptos;

/**
 * Redis key tool.
 * @author Doghole
 */
@Component
@Slf4j
public class Rk {

    static SiteConfig siteConfig;

    static RedissonClient redisson;

    public static String SYSTEM_PREFIX;

    @Autowired
    public void setService(SiteConfig siteConfig, RedissonClient redisson) {
        Rk.siteConfig = siteConfig;
        Rk.redisson = redisson;
        SYSTEM_PREFIX = "doghouse:" + siteConfig.getAddress().hashCode() + ":";
    }

    public static class Gravatar {

        public static final String ID = "gravatar:";

        public static final String GRAVATAR_PREFIX = "image:";

        public static final String EMAIL_HASH_PREFIX = "email-hash:";

        public static final String PRIVATE_HASH_PREFIX = "private-hash:";

        public static final String SALT = "~D09H0U5E-9R4V474R^_^";

        private static String getGravatarKey(String subfix) {
            return SYSTEM_PREFIX + ID + subfix;
        }

        public static RBucket<Object> getGravatarBucket(String dogHash, int size) {
            return redisson.getBucket(getGravatarKey(GRAVATAR_PREFIX + dogHash + ":" + size));
        }

        public static void clearGravatarCache() {
            for (String name : redisson.getKeys().getKeysByPattern(getGravatarKey(GRAVATAR_PREFIX + "*"))) {
                redisson.getBucket(name).deleteAsync();
            }
        }

        public static String prepareDogHash(String email) {
            if (email == null) {
                email = "";
            }
            email = email.toLowerCase(Locale.ENGLISH);

            RBucket<String> gravatarHashBucket = redisson.getBucket(getGravatarKey(EMAIL_HASH_PREFIX + email));
            if (gravatarHashBucket.isExists()) {
                return gravatarHashBucket.get();
            }

            byte[] hash = Cryptos.sha3((email + SALT).getBytes(), 256);

            List<Long> list = new ArrayList<>();

            for (int i = 0; i < 4; i++) {
                Long x = 0L;
                for (int j = 0; j < 8; j++) {
                    x |= (((long) hash[i * 8 + j]) & 0xFFL) << ((7 - j) * 8);
                }
                i++;
                for (int j = 0; j < 8; j++) {
                    x ^= (((long) hash[i * 8 + j]) & 0xFFL) << ((7 - j) * 8);
                }
                if (x < 0) {
                    list.add(0L);
                    list.add(Math.abs(x));
                }
                else {
                    list.add(x);
                }
            }

            String dogHash = Sqids.builder().build().encode(list);
            gravatarHashBucket.set(dogHash);
            String realHash = Cryptos.sha256(email);

            redisson.getBucket(getGravatarKey(PRIVATE_HASH_PREFIX + dogHash))
                .set(realHash);

            log.info("Email: {}, real hash: {}, dog hash: {}", email, realHash, dogHash);

            return dogHash;
        }

        public static String getRealHash(String dogHash) {
            RBucket<String> email = redisson.getBucket(getGravatarKey(PRIVATE_HASH_PREFIX + dogHash));
            return email.get();
        }
    }
}
