package ru.yandex.webmaster3.core.searchquery;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import com.google.protobuf.ByteString;
import org.apache.commons.lang3.StringUtils;

/**
 * @author aherman
 */
public class QueryId {
    private static final long HASH_KEY_1 = 0x728dc3a1c4b2b96cL;
    private static final long HASH_KEY_2 = 0x21e604856ad44214L;

    private final long queryId;

    public QueryId(long queryId) {
        this.queryId = queryId;
    }

    public long getQueryId() {
        return queryId;
    }

    @Override
    public String toString() {
        return toStringId();
    }

    public String toStringId() {
        return String.format("%1$016x", queryId);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        QueryId queryId1 = (QueryId) o;

        return queryId == queryId1.queryId;
    }

    @Override
    public int hashCode() {
        return (int) (queryId ^ (queryId >>> 32));
    }

    public static Optional<QueryId> fromStringId(String queryIdStr) {
        queryIdStr = StringUtils.trimToEmpty(queryIdStr);
        if (queryIdStr.length() != 16) {
            return Optional.empty();
        }
        return Optional.of(new QueryId(Long.parseUnsignedLong(queryIdStr, 16)));
    }

    public static QueryId textToId(String queryText) {
        HashFunction hashFunction = Hashing.sipHash24(HASH_KEY_1, HASH_KEY_2);
        return new QueryId(hashFunction.hashString(queryText, StandardCharsets.UTF_8).asLong());
    }

    public static QueryId textToId(ByteString queryText) {
        HashFunction hashFunction = Hashing.sipHash24(HASH_KEY_1, HASH_KEY_2);
        return new QueryId(hashFunction.hashBytes(queryText.toByteArray()).asLong());
    }

    public static Set<QueryId> textToId(Set<String> queries){
        return queries.stream().map(QueryId::textToId).collect(Collectors.toSet());
    }

    public static Set<QueryId> textToId(List<String> queries){
        return queries.stream().map(QueryId::textToId).collect(Collectors.toSet());
    }
}
