# базовая директория может быть задана с помощью переменной cmake MKL_ROOT (самый высокий приоритет)
# или с помощью переменной окружения MKL_ROOT.
# Если MKL_ROOT не задан, то ищет в стандартных путях:
#    на Windows в Program Files или Program Files (x86) в директории Intel/oneAPI/mkl/latest
#    на Linux в штатных путях (в корне или /usr)
#
# использует tbb threading model, соглашение ILP64 на 64 битах, cdecl на 32
#   (при необходимости можно добавить опции...)
# можно задать пользовательскую версию библитеки
#   (если создана своя версия с подможеством функций с помощью intel compiler):
#   MKL_CUSTOM_LIBRARY_NAME  - имя библиотеки
#   MKL_CUSTOM_LIBRARY_DIR   - путь к пользовательской библиотеки без lib/<сиффикс> (может быть вне MKL_ROOT)
#   Заголовочные файлы в этом случае сперва ищутся в ${MKL_CUSTOM_LIBRARY_DIR}/include, а затем уже внутри MKL_ROOT 


# в первую очередь пытаемся найти mkl с помощью pkgconfig, если применимо
if (NOT MKL_FOUND)
    if(NOT WIN32 AND NOT MKL_CUSTOM_LIBRARY_NAME AND NOT MKL_ROOT)
        find_package(PkgConfig QUIET)
        if(PkgConfig_FOUND)
            #ищем среди разных реализаций потоков в порядке приоритета
            pkg_check_modules(MKL QUIET mkl-dynamic-ilp64-tbb)
            if (NOT MKL_FOUND)
                pkg_check_modules(MKL QUIET mkl-dynamic-ilp64-iomp)
            endif(NOT MKL_FOUND)

            if (NOT MKL_FOUND)
                pkg_check_modules(MKL QUIET mkl-dynamic-ilp64-seq)
            endif(NOT MKL_FOUND)
        endif(PkgConfig_FOUND)
    endif()
endif(NOT MKL_FOUND)
# если не нашли через PkgConfig, то ищмем самостоятельно
if (NOT MKL_FOUND)
    macro(MKL_FIND_LIBRARY  LIB_VAR LIB_FILE_NAME)

        find_library(${LIB_VAR} NAMES ${LIB_FILE_NAME}
           PATHS
           ${MKL_SEARCH_LIBRARY_DIRS}
           PATH_SUFFIXES ${MKL_SEARCH_LIBRARY_DIR_SUFFIX}
        )

        get_filename_component(LIB_DIR  ${${LIB_VAR}} DIRECTORY)
        get_filename_component(LIB_NAME ${${LIB_VAR}} NAME)


        if (${LIB_DIR} IN_LIST MKL_LIBRARY_DIRS)
        else()
            set(MKL_LIBRARY_DIRS ${MKL_LIBRARY_DIRS} ${LIB_DIR})
        endif()
        set(MKL_REQIRED_LIBS ${MKL_REQIRED_LIBS} ${LIB_VAR})
    endmacro()

    if(WIN32)
        cmake_policy(VERSION 3.2)

        # в переменных окружения могут быть пути с разделителем \.
        # если пыти с разными разделителями, то могут быть проблемы, поэтому переводим
        # все к /
        if(NOT MKL_ROOT)
            set(set MKL_ROOT $ENV{MKLROOT})
        endif(NOT MKL_ROOT)
        if(MKL_ROOT)
            string(REGEX REPLACE "\\\\" "/" MKL_ROOT    MKL_ROOT)
        endif(MKL_ROOT)
        string(REGEX REPLACE "\\\\" "/" PROGFILES    $ENV{PROGRAMFILES})
        string(REGEX REPLACE "\\\\" "/" PROGFILESX86 $ENV{PROGRAMFILES\(x86\)})

        if(MKL_ROOT)
            set(MKL_SEARCH_DIRS  ${MKL_ROOT})
        else(MKL_ROOT)
            set(MKL_WINSTD_DIR  "Intel/oneAPI/mkl/latest")
            set(MKL_SEARCH_DIRS "${PROGFILES}/${MKL_WINSTD_DIR}" "${PROGFILESX86}/${MKL_WINSTD_DIR}")
        endif(MKL_ROOT)
        set(MKL_SEARCH_INCLUDE_DIRS ${MKL_SEARCH_DIRS})
        set(MKL_SEARCH_LIBRARY_DIRS ${MKL_SEARCH_DIRS})
        set(MKL_SEARCH_INCLUDE_DIR_SUFFIX include)
        if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
            if(CMAKE_SIZEOF_VOID_P EQUAL 4)
                set(MKL_SEARCH_LIBRARY_DEF_SUFFIX "ia32_win")
            else(CMAKE_SIZEOF_VOID_P EQUAL 4)
                set(MKL_SEARCH_LIBRARY_DEF_SUFFIX "intel64_win")
            endif(CMAKE_SIZEOF_VOID_P EQUAL 4)
        endif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
        set(MKL_SEARCH_LIBRARY_DIR_SUFFIX   "lib/${MKL_SEARCH_LIBRARY_DEF_SUFFIX}")

        #todo возможно сделать опцию, static или dll
        set(MKL_LIB_FILE_SUFFIX "_dll")

    else(WIN32)

        if(NOT MKL_ROOT)
            set(MKL_ROOT    $ENV{MKLROOT})
        endif(NOT MKL_ROOT)



        if (MKL_ROOT)
            set(MKL_SEARCH_INCLUDE_DIRS ${MKL_ROOT}/include)
        else(MKL_ROOT)
            set(MKL_SEARCH_INCLUDE_DIRS  include local/include)
        endif(MKL_ROOT)

        if(CMAKE_SIZEOF_VOID_P EQUAL 4)
            if (MKL_ROOT)
                set(MKL_SEARCH_LIBRARY_DIRS ${MKL_ROOT}/lib)
            else (MKL_ROOT)
                set(MKL_SEARCH_LIBRARY_DIRS lib local/lib lib/i386-linux-gnu)
            endif(MKL_ROOT)
        elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
            if (MKL_ROOT)
                set(MKL_SEARCH_LIBRARY_DIRS ${MKL_ROOT}/lib64 ${MKL_ROOT}/lib/intel64)
            else(MKL_ROOT)
                set(MKL_SEARCH_LIBRARY_DIRS lib64 lib/x86_64-linux-gnu local/lib64)
            endif(MKL_ROOT)

            #взято из готового примера - проверить необходимость
            set(ABI "-m64")
            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ABI}")
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ABI}")
        endif(CMAKE_SIZEOF_VOID_P EQUAL 4)
    endif(WIN32)


    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
        #todo возможно сделать опцию выбора между ILP64 и LP64 (MKL_LONG 64 или 32)
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMKL_ILP64")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMKL_ILP64")
    endif(CMAKE_SIZEOF_VOID_P EQUAL 8)


    if(MKL_CUSTOM_LIBRARY_DIR)
        set(MKL_SEARCH_INCLUDE_DIRS ${MKL_CUSTOM_LIBRARY_DIR} ${MKL_SEARCH_INCLUDE_DIRS})
    endif(MKL_CUSTOM_LIBRARY_DIR)

    find_path(MKL_INCLUDE_DIR NAMES mkl.h
       PATHS
       ${MKL_SEARCH_INCLUDE_DIRS}
       PATH_SUFFIXES ${MKL_SEARCH_INCLUDE_DIR_SUFFIX}
    )

    if (NOT MKL_CUSTOM_LIBRARY_NAME)
        if(CMAKE_SIZEOF_VOID_P EQUAL 4)
            MKL_FIND_LIBRARY(MKL_INTERFACE_LIBRARY mkl_intel_c${MKL_LIB_FILE_SUFFIX})
        elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
            MKL_FIND_LIBRARY(MKL_INTERFACE_LIBRARY mkl_intel_ilp64${MKL_LIB_FILE_SUFFIX})
        endif(CMAKE_SIZEOF_VOID_P EQUAL 4)
        MKL_FIND_LIBRARY(MKL_CORE_LIBRARY mkl_core${MKL_LIB_FILE_SUFFIX})

        MKL_FIND_LIBRARY(MKL_THREAD_LIBRARY mkl_tbb_thread${MKL_LIB_FILE_SUFFIX})
        if(NOT WIN32)
            MKL_FIND_LIBRARY(MKL_TBB_LIBRARY tbb)
        endif(NOT WIN32)
    else(NOT MKL_CUSTOM_LIBRARY_NAME)
        set(MKL_SEARCH_LIBRARY_DIRS ${MKL_SEARCH_LIBRARY_DIRS} ${MKL_CUSTOM_LIBRARY_DIR})
        MKL_FIND_LIBRARY(MKL_CUSTOM_LIBRARY ${MKL_CUSTOM_LIBRARY_NAME})
    endif(NOT MKL_CUSTOM_LIBRARY_NAME)

    include(FindPackageHandleStandardArgs)


    find_package_handle_standard_args(MKL
            REQUIRED_VARS MKL_INCLUDE_DIR ${MKL_REQIRED_LIBS}
            )
    if(MKL_FOUND)
        foreach(MKL_LIB ${MKL_REQIRED_LIBS})
            set(MKL_LIBRARIES ${MKL_LIBRARIES} ${${MKL_LIB}})
        endforeach()
        set(MKL_INCLUDE_DIRS ${MKL_INCLUDE_DIR})

    endif(MKL_FOUND)
endif()

