################################################################################
#  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.
################################################################################
from __future__ import print_function

import io
import os
import sys

from setuptools import setup
from shutil import rmtree
from xml.etree import ElementTree as ET

PACKAGE_NAME = 'apache-flink-connector-aws'
# Source files, directories
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
POM_FILE = os.path.join(CURRENT_DIR, '../pom.xml')
README_FILE = os.path.join(CURRENT_DIR, 'README.txt')

# Generated files and directories
VERSION_FILE = os.path.join(CURRENT_DIR, 'pyflink/datastream/connectors/aws_connector_version.py')
DEPENDENCY_FILE = os.path.join(CURRENT_DIR, 'dev/dev-requirements.txt')


# Removes a file or directory if exists.
def remove_if_exists(file_path):
    if os.path.exists(file_path):
        if os.path.isfile(file_path):
            os.remove(file_path)
        if os.path.isdir(file_path):
            rmtree(file_path)


# Reads the content of the README.txt file.
def readme_content():
    with io.open(README_FILE, 'r', encoding='utf-8') as f:
        return f.read()


# Reads the parameters used by the setup command.
# The source is the aws_connector_version.py and the README.txt.
def setup_parameters():
    try:
        exec(open(VERSION_FILE).read())
        return locals()['__connector_version__'], locals()['__flink_dependency__'], readme_content()
    except IOError:
        print("Failed to load PyFlink version file for packaging. " +
              "'%s' not found!" % VERSION_FILE,
              file=sys.stderr)
        sys.exit(-1)


# Reads and parses the flink-connector-aws main pom.xml.
# Based on the version data in the pom.xml prepares the pyflink dir:
#  - Generates aws_connector_version.py
#  - Generates dev-requirements.txt
#  - Copies the flink-sql-connector-kinesis.jar to the pyflink/lib dir
def prepare_pyflink_dir():
    # source files
    pom_root = ET.parse(POM_FILE).getroot()
    flink_version = pom_root.findall(
        "./{http://maven.apache.org/POM/4.0.0}properties/" +
        "{http://maven.apache.org/POM/4.0.0}flink.version"
    )[0].text
    connector_version = pom_root.findall(
        "./{http://maven.apache.org/POM/4.0.0}version")[0].text.replace("-SNAPSHOT", ".dev0")

    # Pin to the minor version (e.g., >=1.19.1,<1.20.0) to allow patch updates
    # but prevent major/minor version upgrades
    version_parts = flink_version.split('.')
    if len(version_parts) >= 2:
        next_minor = str(int(version_parts[1]) + 1)
        next_version = version_parts[0] + '.' + next_minor + '.0'
        flink_dependency = "apache-flink>=" + flink_version + ",<" + next_version
    else:
        # Fallback to exact match if version format is unexpected
        print("Falling back to exact match for unexpected version format: " + flink_version)
        flink_dependency = "apache-flink==" + flink_version

    with io.open(VERSION_FILE, 'w', encoding='utf-8') as f:
        f.write('# Generated file, do not edit\n')
        f.write('__connector_version__ = "' + connector_version + '"\n')
        f.write('__flink_dependency__ = "' + flink_dependency + '"\n')

    with io.open(DEPENDENCY_FILE, 'w', encoding='utf-8') as f:
        f.write('# Generated file, do not edit\n')
        f.write(flink_dependency + '\n')

# Main
print("Python version used to package: " + sys.version)

# Python version check
if sys.version_info < (3, 8):
    print("Python versions prior to 3.8 are not supported for PyFlink.",
          file=sys.stderr)
    sys.exit(-1)

# Checks the running environment:
#  - In the connector source root directory - package preparation
#  - Otherwise - package deployment
in_flink_source = os.path.isfile(
    "../flink-connector-aws/flink-connector-aws-kinesis-streams/src/main" +
    "/java/org/apache/flink/connector/kinesis/source/KinesisStreamsSource.java")

# Cleans up the generated files and directories and regenerate them.
if in_flink_source:
    remove_if_exists(VERSION_FILE)
    remove_if_exists(DEPENDENCY_FILE)
    prepare_pyflink_dir()
    print("\nPreparing Flink AWS connector package")

# Reads the current setup data from the aws_connector_version.py file and the README.txt
(connector_version, flink_dependency, long_description) = setup_parameters()

print("\nConnector version: " + connector_version)
print("Flink dependency: " + flink_dependency + "\n")

if in_flink_source:
    # Removes temporary directory used by the setup tool
    remove_if_exists(PACKAGE_NAME.replace('-', '_') + '.egg-info')

# Runs the python setup
setup(
    name=PACKAGE_NAME,
    version=connector_version,
    include_package_data=True,
    url='https://flink.apache.org',
    license='https://www.apache.org/licenses/LICENSE-2.0',
    author='Apache Software Foundation',
    author_email='dev@flink.apache.org',
    python_requires='>=3.8',
    install_requires=[flink_dependency],
    description='Apache Flink Python AWS Connector API',
    long_description=long_description,
    long_description_content_type='text/plain',
    zip_safe=False,
    py_modules=[
        "pyflink"
    ],
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'License :: OSI Approved :: Apache Software License',
        'Programming Language :: Python :: 3.8',
        'Programming Language :: Python :: 3.9',
        'Programming Language :: Python :: 3.10',
        'Programming Language :: Python :: 3.11']
)

print("\nFlink AWS connector package is ready\n")
