local M = {}

local function configureWarningsForSolutionVisualStudio()
  configuration {"vs*"}
    -- ignore some warnings
    linkoptions {
      '/ignore:4221', -- This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
      '/ignore:4099', -- no pdb found
    }
    buildoptions {
      '/Wall',        -- enable all

      -- completely useless warning
      '/wd4061', -- enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label
      '/wd4062', -- enumerator 'identifier' in switch of enum 'enumeration' is not handled
      '/wd4100', -- 'identifier' : unreferenced formal parameter
      '/wd4201', -- nonstandard extension used : nameless struct/union (NB: actively used, supported on all platforms)
      '/wd4324', -- 'struct_name' : structure was padded due to __declspec(align())
      '/wd4510', -- 'class' : default constructor could not be generated
      '/wd4512', -- 'class' : assignment operator could not be generated
      '/wd4514', -- 'function' : unreferenced inline function has been removed
      '/wd4571', -- Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught
      '/wd4619', -- warning that does not exist was disabled (boost/gameswf)
      '/wd4710', -- 'function' : function not inlined
      '/wd4711', -- function 'function' selected for inline expansion
      '/wd4820', -- 'bytes' bytes padding added after construct 'member_name'
      '/wd4351', -- new behavior: elements of array 'xxx' will be default initialized (this is standard behaviour)

      -- need to be enabled

      '/wd4005', -- mаcro redefininition
      '/wd4121', -- 'symbol' : alignment of a member was sensitive to packing
      '/wd4189', -- local variable is initialized but not referenced
      '/wd4245', -- 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
      '/wd4350', -- behaviour change
      '/wd4365', -- 'action' : conversion from 'type_1' to 'type_2', signed/unsigned mismatch
      '/wd4389', -- 'operator' : signed/unsigned mismatch
      '/wd4505', -- 'function' : unreferenced local function has been removed
      '/wd4548', -- expression before comma has no effect; expected expression with side-effect (NB: would like to have it enabled, but malloc.h triggers it =/ )
      '/wd4625', -- 'derived class' : copy constructor could not be generated because a base class copy constructor is inaccessible
      '/wd4626', -- 'derived class' : assignment operator could not be generated because a base class assignment operator is inaccessible
      '/wd4640', -- 'instance' : construction of local static object is not thread-safe
      '/wd4668', -- 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'

      -- must be enabled
      '/wd4127', -- conditional expression is constant
      '/wd4242', -- 'identifier' : conversion from 'type1' to 'type2', possible loss of data
      '/wd4244', -- 'conversion' conversion from 'type1' to 'type2', possible loss of data
      '/wd4263', -- 'function' : does not override any virtual member function
      '/wd4264', -- 'function' : no override any virtual member function
      '/wd4265', -- 'class' : class has virtual functions, but destructor is not virtual
      '/wd4266', -- 'function' : no override available for virtual member function from base 'type'; function is hidden (NB: a derived class did not override all overloads of a virtual function)
      '/wd4310', -- cast truncates constant value
      '/wd4702', -- unreachable code
    }

    -- warning-related defines
    defines {
      '_SCL_SECURE_NO_WARNINGS',
      '_CRT_SECURE_NO_WARNINGS',
      '_CRT_SECURE_NO_DEPRECATE',
      '_HAS_EXCEPTIONS=0',
      'GLF_NEW_NO_THROW',
      '_NO_CC_DBGWIN',
      'INCL_WINSOCK_API_TYPEDEFS=1', -- added to avoid _bug_ in ws2tcpip, they actually use define incorrectly, but we don't really care
      '_WINSOCK_DEPRECATED_NO_WARNINGS',
    }
end

local function configureWarningsForSolutionXcode()
  configuration {"xcode*"}
    -- enable most
    buildoptions {
      '-Wall', '-Wextra', '-Weffc++', -- not using -Weverything, it's usage discouraged by clang developers and it might contain buggy warnings
    }
    -- ignore some warnings
    buildoptions {
      '-Wno-unused-parameter',      -- /wd4100 whole idea is broken, because overriding method might not need an argument
      '-Wno-trigraphs',             -- trigraphs in constants are not converted, that's exactly what any sane person would expected
      '-Wno-switch-enum',           -- /wd4061
      '-Wno-switch',                -- /wd4061
      '-Wno-missing-selector-name', -- /wd4061
      '-Wno-overloaded-virtual',    -- missing overload keyword
      '-Wno-unused-function',       -- maybe can be enabled, but actually it's harmless and can be helpful for debugging
      '-Wno-missing-braces',        -- triggers numerous warnings in math constants and initialization of subobjects
      '-Wno-ignored-qualifiers',    -- sin by GLOTonGLWT / gameswf
      '-Wno-unknown-pragmas',       -- can't find a reasonable alternative solution, it's either removing all regions or -fms-extensions, neither is very good
      '-Wno-sign-compare',          -- would like to have it, but it's triggered even on == comparison, way too many false positives
      '-Wno-reorder',               -- would like to have it, but it would require to change almost all ctors... =(
                                    -- + msvc doesn't have such warning, it would be too easy to use wrong order while using msvc, as a result ios build will be broken too often
    }
    -- maybe should be enabled later
    buildoptions {
      '-Wno-semicolon-before-method-body',  -- sin by Tracking lib
      '-Wno-uninitialized',                 -- sin by Tracking lib
      '-Wno-incomplete-implementation',     -- sin by Tracking lib
      '-Wno-unused-variable',               -- sin by Gaia / bne_lib
      '-Wno-unused-value',                  -- sin by GLF (stream.h)
      '-Wno-format',                        -- sin by GLWTManager / ArkWriter
      '-Wno-delete-non-virtual-dtor',       -- sin by SocialLib / CCOnline
    }

    if _OPTIONS.xcode7 ~= nil then
      defines {
        'SDK_IOS9',
      }
      buildoptions {
      -- XCode 7 is way stricter on standard
      '-Wno-inconsistent-missing-override',
      '-Wno-unused-local-typedef',
      '-Wno-deprecated-declarations',
      '-Wno-shorten-64-to-32',
      }
    end
end

function M.configureWarningsForSolution()
  solution(solution().name)
  configureWarningsForSolutionVisualStudio()
  configureWarningsForSolutionXcode()
end

function M.fatalWarningsForProject(projectName)
  M.fatalWarningsForProjects({projectName})
end

function M.fatalWarningsForProjects(projectNames)
  local sln = solution(solution().name)
  for _, name in pairs(projectNames) do
    if (sln.projects[name]) then
      project(name)
      configuration   {"vs*"}
        flags         { 'FatalWarnings' }
        linkoptions   { '/WX' }
        buildoptions  { '/WX' }

      configuration   {"xcode*"}
        flags         { 'FatalWarnings' }
        buildoptions  { '-Werror' }
    end
  end
end

return M
