// BlockyFroggy
// Created by John Ryland on 17/3/19
// Copyright © 2019 John Ryland. All rights reserved.
#pragma once
#ifndef Context_h
#define Context_h


#include <cstdio>
#include <vector>


class DatabaseContext;
class EventContext;
class ActionContext;


class LogContext
{
public:
  virtual void LogX(int level, const char* tag, const char* file, const char* func, int line, const char* fmt, ...)
  {
    printf("[%s] fall back logger called: %s\n", tag, fmt);
  }
};


class Context
{
public:
  inline Context* getContext() { return this; } // So can use via inheritance or composition
  // Can put what ever in here that is context that is needed
  virtual LogContext* getLogContext() { return &logger; }
  /*
  virtual DatabaseContext* getDatabaseContext() = 0;
  virtual EventContext* getEventContext() = 0;
  virtual ActionContext* getActionContext() = 0;
  */
  const char* getLogTag() { return m_tag; }
  const char* m_tag = "Context";
  LogContext logger;
};


template <typename ...T>
struct FalseT : std::false_type
{
};


template <typename ...T>
inline Context* getContext(T...)
{
  static_assert(FalseT<T...>::value , "implement \"inline Context* getContext()\" in the desired scope");
}


template <typename ...T>
inline const char* getLogTag(T...)
{
  static_assert(FalseT<T...>::value , "implement \"inline const char* getLogTag()\" in the desired scope");
}


#define LOG_X(level, ...)     getContext()->getLogContext()->LogX(level, getLogTag(), __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)


#endif /* Context_h */

