/*++

Module Name:

  Common.hpp

Notices:

  Dial Module common.

Author:

  Copyright (c) Prepodobny Alen

  mailto: alienufo@inbox.ru
  mailto: ufocomp@gmail.com

--*/

#ifndef APOSTOL_DM_COMMON_HPP
#define APOSTOL_DM_COMMON_HPP
//----------------------------------------------------------------------------------------------------------------------

#define BPS_PGP_HASH "SHA512"
#define BM_PREFIX "BM-"
//----------------------------------------------------------------------------------------------------------------------

#ifdef  __cplusplus
extern "C++" {
#endif // __cplusplus

namespace Apostol {

    namespace Common {

        //--------------------------------------------------------------------------------------------------------------

        //-- CCustomModule ---------------------------------------------------------------------------------------------

        //--------------------------------------------------------------------------------------------------------------

        class CCustomModule: public CApostolModule {
        protected:

            CStringList m_Module;

            CJSON m_OAuth2;

            CString m_pgpModuleKey;
            CString m_pgpPublicKey;
            CString m_pgpPassphrase;

            CProcessStatus m_Status;

            int m_SyncPeriod;

            void InitMethods() override;

            template<class ClassName>
            void UpdateServerList(TPairs<ClassName> &ClassList, const CString &Key) {
                CStringPairs ServerList;
                CStringList Keys;

                ParsePGPKey(Key, ServerList, Keys);

                if (ServerList.Count() != 0) {
                    CStringPairs::ConstEnumerator em(ServerList);
                    while (em.MoveNext()) {
                        const auto &caCurrent = em.Current();
                        int index = ClassList.IndexOfName(caCurrent.Name());

                        if (index == -1) {
                            index = ClassList.AddPair(caCurrent.Name(), ClassName(caCurrent.Name(), CLocation(caCurrent.Value())));
                            auto &Context = ClassList[index].Value();
                            Context.PGP().Add(CKeyContext(CString("PUBLIC"), Key));
                            Context.PGP().Add(CKeyContext(caCurrent.Name(), CString()));
                        } else {
                            auto &Context = ClassList[index].Value();
                            Context.URL() = caCurrent.Value();
                            Context.PGP().First().Key = Key;
                        }

                        auto &Context = ClassList[index].Value();
                        Context.BTCKeys() = Keys;

                        if (Context.Status() == Context::csInitialization) {
                            UpdateOAuth2(Context, m_OAuth2.Object());
                        }
                    }
                }
            }
            //----------------------------------------------------------------------------------------------------------

            void CheckProviders(CContext &Context, CDateTime Now);

            void CreateAccessToken(CContext &Context, CProvider &Provider, const CString &Application);
            void UpdateAccessToken(CContext &Context, CProvider &Provider, const CString &Application);

            void ParsePGPKey(const CString &Key, CStringPairs &ServerList, CStringList &BTCKeys);

            void ModuleService(CContext &Context);
            void ModuleStatus(CContext &Context);
            void ModuleNew(CContext &Context);
            void ModuleAuthorize(CContext &Context);

            static CString GetParam(const CHTTPRequest &Request, const CString &Key);

            void DoGet(CHTTPServerConnection *AConnection) override;

            virtual void DoPost(CHTTPServerConnection *AConnection);
            virtual void DoAPI(CHTTPServerConnection *AConnection);

            virtual void DoAccount(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI) abstract;
            virtual void DoDeal(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI, const CString &Action) abstract;
            virtual void DoProxy(CHTTPServerConnection *AConnection, const CString &Method, const CString &URI) abstract;
            virtual void DoSignature(CHTTPServerConnection *AConnection) abstract;

        public:

            explicit CCustomModule(CModuleProcess *AProcess, const CString &ModuleName, const CString &SectionName);

            ~CCustomModule() override = default;

            void Initialization(CModuleProcess *AProcess) override;
            bool Enabled() override;

            virtual void Reload() abstract;

            static CString ToString(unsigned long Value);
            static void JsonStringToKey(const CString &String, CString &Code, CString &Key);

            static void CheckKeyForNull(LPCTSTR Key, LPCTSTR Value);

            static void CheckDeal(const CDeal &Deal);
            static int CheckFee(const CString &Fee);

            static bool CheckVerifyPGPSignature(int VerifyPGPSignature, CString &Message);
            static int VerifyPGPSignature(const CString &ClearText, const CString &Key, CString &Message);

            static bool FindURLInLine(const CString &Line, CStringList &List);
            static void UpdateOAuth2(CContext &Context, const CJSONObject &OAuth2);
            static void UpdateProviders(CProviders &Providers, const CJSONObject &Data);

            static CHTTPRequest::CContentType StringToContentType(const CString &ContentType);
        };

    }
}

using namespace Apostol::Common;
#ifdef  __cplusplus
}
#endif // __cplusplus

#endif //APOSTOL_DM_COMMON_HPP
