//pragma solidity >=0.6.10 <0.8.20;
pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;

import "../Table.sol";
import "./Provider.sol";
import "./Utils.sol";

contract Catalog {
    event CreateResult(int256 count);
    event InsertResult(int256 count);
    event UpdateResult(int256 count);
    event RemoveResult(int256 count);
    
    
    TableFactory tableFactory = TableFactory(0x1001); 
    Utils utils = new Utils();
    Provider provider = new Provider();
    string constant TABLE_SUFFIX = "_catalog";
    string constant KEY_NAME = "key";
    string constant KEY_VALUE = "key";
    
    struct CatalogData{
        string  id;
        string parent_id;
        string  other_params;
        int256  create_time;
        int256  update_time;
    }
    
    function selectByParentId(string memory table_prefix,string memory parent_id)
    public
    view
    returns (CatalogData[]){
        if(provider.existByPrefix(table_prefix)==false){
            revert("table_prefix not exists");
        }
         //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, TABLE_SUFFIX));
        
        Table table = tableFactory.openTable(table_name);

        Condition condition = table.newCondition();
        condition.EQ("parent_id", parent_id);
        
        Entries entries = table.select(KEY_VALUE, condition);
         uint256  dataLen =   uint256(entries.size());
        CatalogData[] memory catalogDatas =  new CatalogData[](dataLen);
        
        for (uint256 i = 0; i < dataLen; ++i) {
            Entry entry = entries.get(int256(i));
            catalogDatas[i]=CatalogData(entry.getString("id"),entry.getString("parent_id"),entry.getString("other_params"),entry.getInt("create_time"),entry.getInt("update_time"));
        }

        return (catalogDatas);
    }
    
    function selectById(string memory table_prefix,string memory id)
    public
    view
    returns (CatalogData[]){
        if(provider.existByPrefix(table_prefix)==false){
            revert("table_prefix not exists");
        }
         //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, TABLE_SUFFIX));
        
        Table table = tableFactory.openTable(table_name);

        Condition condition = table.newCondition();
        condition.EQ("id", id);
        
        Entries entries = table.select(KEY_VALUE, condition);
        uint256 dataLen = uint256(entries.size());
        CatalogData[] memory catalogDatas =  new CatalogData[](dataLen);
        
        for (uint256 i = 0; i < dataLen; ++i) {
            Entry entry = entries.get(int256(i));
            catalogDatas[i]=CatalogData(entry.getString("id"),entry.getString("parent_id"),entry.getString("other_params"),entry.getInt("create_time"),entry.getInt("update_time"));
        }

        return (catalogDatas);
    }
    
    function insert(string memory id,string memory other_params,string memory parent_id,int256 create_time,int256 update_time) 
    public 
    returns(int256,string memory){
        //表格前缀
        
        string memory table_prefix = provider.selectPrefixByAddr(utils.toString(tx.origin));
        if(utils.strIsEmpty(table_prefix)){
            revert("can not find your catalog table, are you regiester as provder?");
        }
        //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, TABLE_SUFFIX));
        Table table = tableFactory.openTable(table_name);
        
        //id重复校验
        if(existById(id,table)){
            revert("id exist, insert failed");
        }
        //parent_id如果不为空则校验父级是否存在
        // if(utils.strIsEmpty(parent_id)){
        //     //不存在
        //     if(!existByParentId(parent_id,table)){
        //         return (0,"parent_id not find");
        //     }
        // }
       
        Entry entry = table.newEntry();
        entry.set(KEY_NAME, KEY_VALUE);
        entry.set("id", id);
        entry.set("other_params", other_params);
        entry.set("parent_id", parent_id);
        entry.set("create_time", create_time);
        entry.set("update_time", update_time);

        int256 count = table.insert(KEY_VALUE, entry);
        if(count>0){
            emit InsertResult(count);
        }
    

        return (count,"success");
    }
    
    function update(string memory id,string memory other_params,string memory parent_id,int256 update_time) 
    public 
    returns(int256,string memory){
        //必填项校验
        if(utils.strIsEmpty(other_params)){
            revert("other_params can not empty");
        }
        if(update_time == 0){
            revert("update_time can not empty");
        }
        
        //表格前缀
        string memory table_prefix = provider.selectPrefixByAddr(utils.toString(tx.origin));
        if(utils.strIsEmpty(table_prefix)){
            revert("can not find your catalog table, are you regiester as provder?");
        }
        //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, "_catalog"));
        Table table = tableFactory.openTable(table_name);
        
        Entry entry = table.newEntry();
        entry.set("other_params",other_params);
        entry.set("parent_id",parent_id);
        entry.set("update_time",update_time);

        Condition condition = table.newCondition();
        condition.EQ("id", id);

        int256 count = table.update(KEY_VALUE, entry, condition);
        if(count>0){
            emit UpdateResult(count);
        }

        return (count,"success");
    }
    
     //根据catalog_id删除
    function remove(string memory catalog_id) 
    public 
    returns (int256) {
        //表格前缀
        string memory table_prefix = provider.selectPrefixByAddr(utils.toString(tx.origin));
        if(utils.strIsEmpty(table_prefix)){
            revert("can not find your catalog table, are you regiester as provder?");
        }
        //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, TABLE_SUFFIX));
        Table table = tableFactory.openTable(table_name);
        
        Condition condition = table.newCondition();
        condition.EQ("id", catalog_id);

        int256 count = table.remove(KEY_VALUE, condition);
        if(count>0){
            emit RemoveResult(count);
        }
        return count;
    }
    
    //判断catalog_id是否有子archives_file
    function existArchivesFileById(string memory catalog_id,string memory table_prefix)
    private
    view
    returns (bool){
        //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, "_archives_file"));
        
        Table table = tableFactory.openTable(table_name);
        Condition condition = table.newCondition();
        condition.EQ("catalog_id", catalog_id);
        Entries entries = table.select("key", condition);
        return entries.size()>0;
        
    }
    
     //根据id判定是否存在
    function existById(string memory id,Table table)
    private
    view
    returns (bool){
        Condition condition = table.newCondition();
        condition.EQ("id", id);
        Entries entries = table.select(KEY_VALUE, condition);
        return entries.size()>0;
    }
    
     //根据parent_id判定是否存在
    function existByParentId(string memory parent_id,Table table)
    private
    view
    returns (bool){
        Condition condition = table.newCondition();
        condition.EQ("parent_id", parent_id);
        Entries entries = table.select(KEY_VALUE, condition);
        return entries.size()>0;
    }
}