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

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

contract File {
    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 = "_file";
    string constant KEY_NAME = "key";
    string constant KEY_VALUE = "key";
    
    struct FileData{
        string  id;
        string  archive_file_id;
        string  other_params;
        int256  create_time;
        int256  update_time;
    }
    
    //查询单个文件
    function selectById(string memory table_prefix,string memory file_id)
    public
    view
    returns (FileData[] memory){
        
        //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, TABLE_SUFFIX));
         Table table = tableFactory.openTable(table_name);

        Condition condition = table.newCondition();
        condition.EQ("id", file_id);
        
        Entries entries = table.select(KEY_VALUE, condition);
        uint256  dataLen =   uint256(entries.size());
        FileData[] memory  files = new FileData[](dataLen);
        
        for (uint256 i = 0; i < dataLen; ++i) {
            Entry entry = entries.get(int256(i));
            files[i]=FileData(entry.getString("id"),entry.getString("archive_file_id"),entry.getString("other_params"),entry.getInt("create_time"),entry.getInt("update_time"));
        
        }
        
        return (files);
    }
    
    
    
    
    //查询某个件下的所有文件
    function selectByCatalogId(string memory table_prefix,string memory archive_file_id)
    public
    view
    returns (FileData[] memory){
        //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, TABLE_SUFFIX));
        Table table = tableFactory.openTable(table_name);

        Condition condition = table.newCondition();
        condition.EQ("archive_file_id", archive_file_id);
        
        Entries entries = table.select(KEY_VALUE, condition);
        uint256  dataLen =   uint256(entries.size());
        FileData[] memory  files = new FileData[](dataLen);
        
        for (uint256 i = 0; i < dataLen; ++i) {
            Entry entry = entries.get(int256(i));
            files[i]=FileData(entry.getString("id"),entry.getString("archive_file_id"),entry.getString("other_params"),entry.getInt("create_time"),entry.getInt("update_time"));
        }
        
        return (files);
    }
    
    
    
    function insert(string memory id,string memory archive_file_id, string memory other_params,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 file table, have you regiestered as a 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 can not repeated");
        }
        
        
        Entry entry = table.newEntry();
        entry.set(KEY_NAME, KEY_VALUE);
        entry.set("id", id);
        entry.set("archive_file_id", archive_file_id);
        entry.set("other_params", other_params);
        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 archive_file_id, string memory other_params,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 file table, have you regiestered as a provder?");
        }
        //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, TABLE_SUFFIX));
        Table table = tableFactory.openTable(table_name);
        
        Entry entry = table.newEntry();
        entry.set("archive_file_id", archive_file_id);
        entry.set("other_params", other_params);
        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");
    }
    
    
    //根据file_id删除
    function remove(string[] memory file_id) 
    public 
    returns (int256) {
        //表格前缀
        string memory table_prefix = provider.selectPrefixByAddr(utils.toString(tx.origin));
        if(utils.strIsEmpty(table_prefix)){
            revert("can not find your file table, have you regiestered as a provder?");
        }
        //确定表格名称
        string memory table_name = string(abi.encodePacked(table_prefix, TABLE_SUFFIX));
        Table table = tableFactory.openTable(table_name);
        int256 count = 0;
        
        for(uint256 i=0;i<file_id.length;i++){
            Condition condition = table.newCondition();
            condition.EQ("id", file_id[i]);
            int256 deleteCount = table.remove(KEY_VALUE, condition);
            if(deleteCount>0){
                count++;
            }
        }

        
        if(count>0){
            emit RemoveResult(count);
        }
        
        return count;
    }
    
    
     //根据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;
    }
    
     //根据archive_file_id判定是否存在
    function existByArchiveFileId(string memory archive_file_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("id", archive_file_id);
        Entries entries = table.select(KEY_VALUE, condition);
        return entries.size()>0;
    }
    
}