package ru.yandex.webmaster3.storage.notifications.dao;

import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import lombok.Setter;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.webmaster3.storage.notifications.NotificationProgress;
import ru.yandex.webmaster3.storage.notifications.NotificationZKHelper;
import ru.yandex.webmaster3.storage.util.yt.YtException;
import ru.yandex.webmaster3.storage.util.yt.lock.CypressProvider;

/**
 * Этот dao заведен для того, чтобы можно было написать тесты на NotificationService не мокая CuratorFramework
 *
 * @author avhaliullin
 */
public class NotificationProgressCypressDao {

    @Autowired
    private CypressProvider cypressProvider;
    @Setter
    private String rootNode;

    public String getRootNode() {
        return rootNode;
    }

    public boolean haveProgressRecord(UUID notificationId) {
        String zkNode = notificationNode(notificationId);
        return cypressProvider.checkExists().forPath(zkNode);
    }

    public Pair<NotificationProgress, Integer> getRecordIfExists(UUID notificationId) {
        if (!haveProgressRecord(notificationId)) {
            return null;
        } else {
            var stat = new CypressProvider.Stat();
            byte[] data = cypressProvider
                    .getData()
                    .storingStatIn(stat)
                    .forPathBinary(notificationNode(notificationId));
            return Pair.of(NotificationZKHelper.getNotificationProgress(data), stat.getVersion() == null ? null : stat.getVersion().intValue());
        }
    }

    public void updateRecord(UUID notificationId, NotificationProgress progress, long version) {
        cypressProvider
                .setData()
                .withVersion(version)
                .forPath(notificationNode(notificationId), NotificationZKHelper.dumpNotificationProgress(progress));
    }

    public void createRecord(UUID notificationId, NotificationProgress progress) {
        cypressProvider
                .create()
                .forPath(
                        notificationNode(notificationId),
                        NotificationZKHelper.dumpNotificationProgress(progress)
                );
    }

    public void deleteRecord(UUID notificationId) {
        cypressProvider.delete().deletingChildrenIfNeeded().forPath(notificationNode(notificationId));
    }

    public List<UUID> listRecords() {
        try {
            // removing leading /
            return cypressProvider.getChildren().forPath(getRootNode()).stream().map(s -> s.substring(1)).map(UUID::fromString)
                    .collect(Collectors.toList());
        } catch (YtException e) {
            return Collections.emptyList();
        }
    }

    private String notificationNode(UUID notificationId) {
        return rootNode + "/" + notificationId;
    }

}
