#!/usr/bin/env python3

# Copyright 2020 Daniel Mensinger

# Licensed 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 sys
import hashlib
import textwrap
import re
from pathlib import Path
from datetime import datetime
import typing as T

class DataFile:
    file_counter = 0

    def __init__(self, path: Path, root: Path):
        self.path = path
        self.id = self.path.relative_to(root)
        self.data_str = f'file_{DataFile.file_counter}_data_' + re.sub('[^a-zA-Z0-9]', '_', self.path.name)
        DataFile.file_counter += 1

        b = self.path.read_bytes()
        self.data = b.decode()
        self.sha256sum = hashlib.sha256(b).hexdigest()

    def __repr__(self) -> str:
        return f'<{type(self).__name__}: [{self.sha256sum}] {self.id}>'

def main() -> int:
    root_dir = Path(__file__).resolve().parents[1]
    mesonbuild_dir = root_dir / 'mesonbuild'
    out_file = mesonbuild_dir / 'mesondata.py'

    data_dirs = mesonbuild_dir.glob('**/data')

    data_files: T.List[DataFile] = []

    for d in data_dirs:
        for p in d.iterdir():
            data_files += [DataFile(p, mesonbuild_dir)]

    print(f'Found {len(data_files)} data files')

    # Generate the data script
    data = ''

    data += textwrap.dedent(f'''\
        # Copyright {datetime.today().year} The Meson development team

        # Licensed 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.


        ####
        ####  WARNING: This is an automatically generated file! Do not edit!
        ####           Generated by {Path(__file__).resolve().relative_to(root_dir)}
        ####


        from pathlib import Path
        import typing as T

        if T.TYPE_CHECKING:
            from .environment import Environment

        ######################
        # BEGIN Data section #
        ######################

    ''')

    for i in data_files:
        data += f"{i.data_str} = '''\\\n{i.data}'''\n\n"

    data += textwrap.dedent(f'''
        ####################
        # END Data section #
        ####################

        class DataFile:
            def __init__(self, path: Path, sha256sum: str, data: str) -> None:
                self.path = path
                self.sha256sum = sha256sum
                self.data = data

            def write_once(self, path: Path) -> None:
                if not path.exists():
                    path.write_text(self.data)

            def write_to_private(self, env: 'Environment') -> Path:
                out_file = Path(env.scratch_dir) / 'data' / self.path.name
                out_file.parent.mkdir(exist_ok=True)
                self.write_once(out_file)
                return out_file


        mesondata = {{
    ''')

    for i in data_files:
        data += textwrap.indent(textwrap.dedent(f"""\
            '{i.id}': DataFile(
                Path('{i.id}'),
                '{i.sha256sum}',
                {i.data_str},
            ),
        """), '    ')

    data += textwrap.dedent('''\
        }
    ''')

    print(f'Updating {out_file}')
    out_file.write_text(data)
    return 0

if __name__ == '__main__':
    sys.exit(main())
