# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import platform
import re
import subprocess
import setuptools
import sys
import multiprocessing
from pprint import pprint
from setuptools.command.build_ext import build_ext
from setuptools.extension import Extension

PACKAGE_NAME = 'pyignite_dbapi'
EXTENSION_NAME = 'pyignite_dbapi._pyignite_dbapi_extension'


def is_a_requirement(req_line):
    return not any([
        req_line.startswith('#'),
        req_line.startswith('-r'),
        len(req_line) == 0,
    ])


install_requirements = []
with open('requirements/install.txt', 'r', encoding='utf-8') as requirements_file:
    for line in requirements_file.readlines():
        line = line.strip('\n')
        if is_a_requirement(line):
            install_requirements.append(line)

with open('README.md', 'r', encoding='utf-8') as readme_file:
    long_description = readme_file.read()

version = None
with open(os.path.join(PACKAGE_NAME, '_version.txt'), 'r') as fd:
    version = fd.read()
    if not version:
        raise RuntimeError('Cannot find version information')

def cmake_project_version(version):
    """
    Strips the extra portion of the project version string to satisfy CMake requirements
    """
    end_index = re.search(r"\d+\.\d+\.\d+", version).end()
    if end_index != -1:
        return version[:end_index]
    return version

def _get_env_variable(name, default='OFF'):
    if name not in os.environ.keys():
        return default
    return os.environ[name]


# Command line flags forwarded to CMake (for debug purpose)
cmake_cmd_args = []
for f in sys.argv:
    if f.startswith('-D'):
        cmake_cmd_args.append(f)


class CMakeExtension(Extension):
    def __init__(self, name, cmake_lists_dir='.', sources=[], **kwa):
        Extension.__init__(self, name, sources=sources, **kwa)
        self.cmake_lists_dir = os.path.abspath(cmake_lists_dir)


class CMakeBuild(build_ext):
    def build_extensions(self):
        try:
            subprocess.check_output(['cmake', '--version'])
        except OSError:
            raise RuntimeError('Cannot find CMake executable')

        for ext in self.extensions:
            ext_dir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
            cfg = 'Release'
            ext_file = os.path.splitext(os.path.basename(self.get_ext_filename(ext.name)))[0]
            python_dir = os.path.dirname(sys.executable) if sys.executable else ""

            cmake_args = [
                f'-DCMAKE_BUILD_TYPE={cfg}',
                f'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{cfg.upper()}={ext_dir}',
                f'-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_{cfg.upper()}={self.build_temp}',
                f'-DEXTENSION_FILENAME={ext_file}',
                f'-DIGNITE_VERSION={cmake_project_version(version)}',
                f'-DPython3_ROOT_DIR={python_dir}'
            ]

            if platform.system() == 'Windows':
                plat = ('x64' if platform.architecture()[0] == '64bit' else 'Win32')
                cmake_args += [
                    '-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE',
                    f'-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_{cfg.upper()}={ext_dir}',
                ]
                if self.compiler.compiler_type == 'msvc':
                    cmake_args += [
                        f'-DCMAKE_GENERATOR_PLATFORM={plat}',
                    ]
                else:
                    raise RuntimeError('Only MSVC is supported for Windows currently')

            cmake_args += cmake_cmd_args

            pprint(cmake_args)

            if not os.path.exists(self.build_temp):
                os.makedirs(self.build_temp)

            cpu_count = multiprocessing.cpu_count()

            # Config and build the extension
            subprocess.check_call(['cmake', ext.cmake_lists_dir] + cmake_args, cwd=self.build_temp)
            subprocess.check_call(['cmake', '--build', '.', '-j', str(cpu_count), '--config', cfg, '-v'],
                                  cwd=self.build_temp)


def run_setup():
    setuptools.setup(
        name=PACKAGE_NAME,
        version=version,
        python_requires='>=3.10',
        author='The Apache Software Foundation',
        author_email='dev@ignite.apache.org',
        description='Apache Ignite 3 DB API Driver',
        long_description=long_description,
        long_description_content_type='text/markdown',
        url='https://github.com/apache/ignite-3/tree/main/modules/platforms/python/dbapi',
        packages=setuptools.find_packages(),
        include_package_data=True,
        ext_modules=[CMakeExtension(EXTENSION_NAME)],
        cmdclass=dict(build_ext=CMakeBuild),
        install_requires=install_requirements,
        license='Apache License 2.0',
        license_files=('LICENSE', 'NOTICE'),
        classifiers=[
            'Programming Language :: C++',
            'Programming Language :: Python',
            'Programming Language :: Python :: 3',
            'Programming Language :: Python :: 3.10',
            'Programming Language :: Python :: 3.11',
            'Programming Language :: Python :: 3.12',
            'Programming Language :: Python :: 3.13',
            'Programming Language :: Python :: 3.14',
            'Programming Language :: Python :: 3 :: Only',
            'Intended Audience :: Developers',
            'Topic :: Database :: Front-Ends',
            'Topic :: Software Development :: Libraries :: Python Modules',
            'Operating System :: MacOS',
            'Operating System :: Microsoft :: Windows',
            'Operating System :: POSIX :: Linux',
        ],
    )


if __name__ == "__main__":
    run_setup()
