package ru.yandex.webmaster3.core.searchquery;

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

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

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

    private final long value;

    public PathId(long value) {
        this.value = value;
    }

    public long getValue() {
        return value;
    }

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

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

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

        PathId pathId1 = (PathId) o;

        return value == pathId1.value;
    }

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

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

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

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

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

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