package zmo.technology.lite.processors;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import zmo.technology.lite.core.ZeroFolders.ZeroFolderEntity;
import zmo.technology.lite.core.ZeroProcessor;
import zmo.technology.lite.core.ZeroRequestGuider;

public class ZeroFolderProcessor extends ZeroProcessor {
    
    protected ZeroFolderProcessor(ZeroRequestGuider guider) {
        super(guider);
    }

    public static ZeroFolderProcessor build(ZeroRequestGuider guider) {
        return new ZeroFolderProcessor(guider);
    }

    private PreparedStatement addFolderPrepared() throws SQLException {
        final String addFolder = "INSERT INTO zero_folder_entity(ID, features, name, mine_type, bytes) VALUES (? ,? ,? ,? ,?)";
        if (!existsPreparedStatement(addFolder))
            registeyPreparedStatement(addFolder);
        return preparedStatement(addFolder);
    }

    public void addFolder(ZeroFolderEntity entity) throws SQLException {
        entity.reset();
        addFolderPrepared().setString(1, entity.uuIDString());
        addFolderPrepared().setString(2, entity.featuresJSONString());
        addFolderPrepared().setString(3, entity.getName());
        addFolderPrepared().setString(4, entity.getMineType());
        addFolderPrepared().setBytes(5, entity.getDatas());
        addFolderPrepared().execute();
    }

    private PreparedStatement rmFolderPrepared() throws SQLException {
        final String rmFolder = "DELETE FROM zero_folder_entity WHERE ID = ?";
        if (!existsPreparedStatement(rmFolder))
            registeyPreparedStatement(rmFolder);
        return preparedStatement(rmFolder);
    }

    public void rmFolder(ZeroFolderEntity entity) throws SQLException {
        rmFolderPrepared().setString(1, entity.uuIDString());
        rmFolderPrepared().execute();
    }

    public void rmFolder(String entityID) throws SQLException {
        rmFolderPrepared().setString(1, entityID);
        rmFolderPrepared().execute();
    }

    private PreparedStatement addRelevancyFolderPrepared() throws SQLException {
        final String addRelevancyFolder = "INSERT INTO zero_folder_relevancy(id, entity_id, relevancy_id, directory, path) VALUES (? ,? ,? ,? ,?)";
        if (!existsPreparedStatement(addRelevancyFolder))
            registeyPreparedStatement(addRelevancyFolder);
        return preparedStatement(addRelevancyFolder);
    }

    public void addRelevancyFolder(ZeroFolderEntity entity) throws SQLException {
        addRelevancyFolderPrepared().setString(1, UUID.randomUUID().toString());
        addRelevancyFolderPrepared().setString(2, entity.uuIDString());
        addRelevancyFolderPrepared().setString(3, entity.getRelevancyID());
        addRelevancyFolderPrepared().setString(4, entity.getDirectory());
        addRelevancyFolderPrepared().setString(5, entity.getPath());
        addRelevancyFolderPrepared().execute();
    }

    private PreparedStatement rmRelevancyFolderPrepared() throws SQLException {
        final String rmRelevancyFolder = "DELETE FROM zero_folder_relevancy WHERE ID = ?";
        if (!existsPreparedStatement(rmRelevancyFolder))
            registeyPreparedStatement(rmRelevancyFolder);
        return preparedStatement(rmRelevancyFolder);
    }

    public void rmRelevancyFolder(ZeroFolderEntity entity) throws SQLException {
        rmRelevancyFolderPrepared().setString(1, entity.uuIDString());
        rmRelevancyFolderPrepared().execute();
    }

    private PreparedStatement fetchFolderInfoPrepared() throws SQLException {
        final String fetchFolderInfo = "SELECT ID, create_time, update_time, features, name, mine_type FROM zero_folder_entity WHERE ID = ? LIMIT 1";
        if (!existsPreparedStatement(fetchFolderInfo))
            registeyPreparedStatement(fetchFolderInfo);
        return preparedStatement(fetchFolderInfo);
    }

    public ZeroFolderEntity fetchFolderInfo(String entityID) throws SQLException {
        fetchFolderInfoPrepared().setString(1, entityID);
        ResultSet set = fetchFolderInfoPrepared().executeQuery();
        if (!set.next())
            throw new SQLException("entity '" + entityID + "' not found");
        return new ZeroFolderEntity(set);
    }

    private PreparedStatement fetchFolderPrepared() throws SQLException {
        final String fetchFolder = "SELECT * FROM zero_folder_entity WHERE ID = ? LIMIT 1";
        if (!existsPreparedStatement(fetchFolder))
            registeyPreparedStatement(fetchFolder);
        return preparedStatement(fetchFolder);
    }

    public ZeroFolderEntity fetchFolder(String entityID) throws SQLException {
        fetchFolderPrepared().setString(1, entityID);
        ResultSet set = fetchFolderPrepared().executeQuery();
        if (!set.next())
            throw new SQLException("entity '" + entityID + "' not found");
        return new ZeroFolderEntity(set);
    }

    private PreparedStatement fetchDataRefPrepared() throws SQLException {
        final String fetchDataRef = "SELECT * FROM zero_folder_view WHERE relevancy_id = ?";
        if (!existsPreparedStatement(fetchDataRef))
            registeyPreparedStatement(fetchDataRef);
        return preparedStatement(fetchDataRef);
    }

    public List<ZeroFolderEntity> fetchDataRef(String dataID) throws SQLException {
        fetchDataRefPrepared().setString(1, dataID);
        ResultSet set = fetchDataRefPrepared().executeQuery();
        List<ZeroFolderEntity> entities = new ArrayList<>();
        while (set.next())
            entities.add(new ZeroFolderEntity(set));
        return entities;
    }

    private PreparedStatement fetchFolderDataByPathPrepared() throws SQLException {
        final String fetchFolderDataByPath = "SELECT * FROM zero_folder_data_view WHERE path = ? LIMIT 1";
        if (!existsPreparedStatement(fetchFolderDataByPath))
            registeyPreparedStatement(fetchFolderDataByPath);
        return preparedStatement(fetchFolderDataByPath);
    }

    public ZeroFolderEntity fetchFolderDataByPath(String path) throws SQLException {
        fetchFolderDataByPathPrepared().setString(1, path);
        ResultSet set = fetchFolderDataByPathPrepared().executeQuery();
        if (!set.next())
            throw new SQLException("path '" + path + "' not found");
        return new ZeroFolderEntity(set);
    }

    private PreparedStatement fetchDataRefCountPrepared() throws SQLException {
        final String fetchDataRefCount = "SELECT count(1) FROM zero_folder_relevancy WHERE relevancy_id = ? AND directory = ?";
        if (!existsPreparedStatement(fetchDataRefCount))
            registeyPreparedStatement(fetchDataRefCount);
        return preparedStatement(fetchDataRefCount);
    }

    public long fetchDataRefCount(String relevancyID, String directory) throws SQLException {
        fetchDataRefCountPrepared().setString(1, relevancyID);
        fetchDataRefCountPrepared().setString(2, directory);
        ResultSet set = fetchDataRefCountPrepared().executeQuery();
        if (!set.next())
            throw new SQLException("query `fetchDataRefCount` faild");
        return set.getLong(1);
    }

    private PreparedStatement fetchLastDataRefIDPrepared() throws SQLException {
        final String fetchLastDataRefID = "SELECT id FROM zero_folder_relevancy WHERE relevancy_id = ? AND directory = ? ORDER BY create_time ASC LIMIT 1";
        if (!existsPreparedStatement(fetchLastDataRefID))
            registeyPreparedStatement(fetchLastDataRefID);
        return preparedStatement(fetchLastDataRefID);
    }

    private PreparedStatement rmLastDataRefPrepared() throws SQLException {
        final String rmLastDataRef = "DELETE FROM zero_folder_relevancy WHERE ID = ?";
        if (!existsPreparedStatement(rmLastDataRef))
            registeyPreparedStatement(rmLastDataRef);
        return preparedStatement(rmLastDataRef);
    }

    public void rmLastDataRef(String relevancyID, String directory) throws SQLException {
        fetchLastDataRefIDPrepared().setString(1, relevancyID);
        fetchLastDataRefIDPrepared().setString(2, directory);
        ResultSet set = fetchLastDataRefIDPrepared().executeQuery();
        if (set.next()) {
            rmLastDataRefPrepared().setString(1, set.getString(1));
            rmLastDataRefPrepared().execute();
        }
    }

    public List<ZeroFolderEntity> fetchDatasRef(String sql) throws SQLException {
        ResultSet set = getStatement().executeQuery(sql);
        List<ZeroFolderEntity> entities = new ArrayList<>();
        while (set.next())
            entities.add(new ZeroFolderEntity(set));
        return entities;
    }

    public long fetchDatasRefCount(String sql) throws SQLException {
        ResultSet set = getStatement().executeQuery(sql);
        if (!set.next())
            throw new SQLException("query `fetchDataRefCount` faild");
        return set.getLong(1);
    }

}
