// AccountModel.h

#pragma once

#include <string>
#include <memory>

using namespace std;

class AccountModel {

public:
    AccountModel() = delete;
    explicit AccountModel(string jsonfilePath);
    virtual ~AccountModel();

public:
    inline const string* UserID() { return this->m_userID.get(); }
    inline const string* Password() { return this->m_password.get(); }
    inline const string* BrokerID() { return this->m_brokerID.get(); }
    inline const string* ProductInfo() { return this->m_productInfo.get(); }
    inline const string* AppID() { return this->m_appID.get(); }
    inline const string* AuthCode() { return this->m_authCode.get(); }
    inline const string* TradeFrontAddress() { return this->m_tradeFrontAddress.get(); }
    inline const string* MarketFrontAddress() { return this->m_marketFrontAddress.get(); }
    inline const string* TradeRuntimeFold() { return this->m_tradeRuntimeFold.get(); }
    inline const string* MarketRuntimeFold() { return this->m_marketRuntimeFold.get(); }
    inline const string* Module() { return this->m_module.get(); }

private:
    bool ParseAccountData();

    bool HintNotFile(string filePath);

private:
    unique_ptr<string> m_jsonfilePath;

    unique_ptr<string> m_userID;
    unique_ptr<string> m_password;
    unique_ptr<string> m_brokerID;
    unique_ptr<string> m_productInfo;
    unique_ptr<string> m_appID;
    unique_ptr<string> m_authCode;
    unique_ptr<string> m_tradeFrontAddress;
    unique_ptr<string> m_marketFrontAddress;
    unique_ptr<string> m_tradeRuntimeFold;
    unique_ptr<string> m_marketRuntimeFold;
    unique_ptr<string> m_module;

};

using AccountUPtr = unique_ptr<AccountModel>;
using AccountSPtr = shared_ptr<AccountModel>;
// AccountModel.cc

#include <onepiece/models/AccountModel.h>

#include <iostream>
#include <fstream>
#include <boost/filesystem.hpp>
#include <rapidjson/document.h>

using namespace rapidjson;

AccountModel::AccountModel(string jsonfilePath): m_jsonfilePath(make_unique<string>(jsonfilePath)) {
    boost::filesystem::exists(this->m_jsonfilePath->data()) ? this->ParseAccountData() : this->HintNotFile(this->m_jsonfilePath->data());
}

bool AccountModel::ParseAccountData() {
    ifstream ifs((*this->m_jsonfilePath).c_str());
    string content((istreambuf_iterator<char>(ifs)), (istreambuf_iterator<char>()));

    Document document;
    document.Parse(content.c_str());

    this->m_userID = (document.HasMember("userID") && document["userID"].IsString()) ? make_unique<string>(document["userID"].GetString()) : nullptr;
    this->m_password = (document.HasMember("password") && document["password"].IsString()) ? make_unique<string>(document["password"].GetString()) : nullptr;
    this->m_brokerID = (document.HasMember("brokerID") && document["brokerID"].IsString()) ? make_unique<string>(document["brokerID"].GetString()) : nullptr;
    this->m_productInfo = (document.HasMember("productInfo") && document["productInfo"].IsString()) ? make_unique<string>(document["productInfo"].GetString()) : nullptr;
    this->m_appID = (document.HasMember("appID") && document["appID"].IsString()) ? make_unique<string>(document["appID"].GetString()) : nullptr;
    this->m_authCode = (document.HasMember("authCode") && document["authCode"].IsString()) ? make_unique<string>(document["authCode"].GetString()) : nullptr;
    this->m_tradeFrontAddress = (document.HasMember("tradeFrontAddress") && document["tradeFrontAddress"].IsString()) ? make_unique<string>(document["tradeFrontAddress"].GetString()) : nullptr;
    this->m_marketFrontAddress = (document.HasMember("marketFrontAddress") && document["marketFrontAddress"].IsString()) ? make_unique<string>(document["marketFrontAddress"].GetString()) : nullptr;
    this->m_tradeRuntimeFold = (document.HasMember("tradeRuntimeFold") && document["tradeRuntimeFold"].IsString()) ? make_unique<string>(document["tradeRuntimeFold"].GetString()) : nullptr;
    this->m_marketRuntimeFold = (document.HasMember("marketRuntimeFold") && document["marketRuntimeFold"].IsString()) ? make_unique<string>(document["marketRuntimeFold"].GetString()) : nullptr;
    this->m_module = (document.HasMember("module") && document["module"].IsString()) ? make_unique<string>(document["module"].GetString()) : nullptr;
    

    // {
    //     cout << "userID: " << *this->UserID() << endl;
    //     cout << "password: " << *this->Password() << endl;
    //     cout << "brokerID: " << *this->BrokerID() << endl;
    //     cout << "tradeFrontAddress: " << *this->TradeFrontAddress() << endl;
    //     cout << "marketFrontAddress: " << *this->MarketFrontAddress() << endl;
    //     cout << "appID: " << *this->AppID() << endl;
    //     cout << "authCode: " << *this->AuthCode() << endl;
    //     cout << "tradeRuntimeFold: " << *this->TradeRuntimeFold() << endl;
    //     cout << "marketRuntimeFold: " << *this->MarketRuntimeFold() << endl;
    //     cout << "productInfo: " << *this->ProductInfo() << endl;
    //     cout << "module: " << *this->Module() << endl;
    // }
    

    return true;
}

bool AccountModel::HintNotFile(string filePath) {
    // write error message to log.
    cout << "filePath: " << filePath << " is not exist." << endl;

    return false;
}


AccountModel::~AccountModel() {
    this->m_userID.reset(nullptr);
    this->m_password.reset(nullptr);
    this->m_brokerID.reset(nullptr);
    this->m_productInfo.reset(nullptr);
    this->m_appID.reset(nullptr);
    this->m_authCode.reset(nullptr);
    this->m_tradeFrontAddress.reset(nullptr);
    this->m_marketFrontAddress.reset(nullptr);
    this->m_tradeRuntimeFold.reset(nullptr);
    this->m_marketRuntimeFold.reset(nullptr);
    this->m_module.reset(nullptr);
}