#!/usr/bin/python3
# SPDX-License-Identifier: LicenseRef-Proprietary
"""Adopt compact chrome only for an exact untouched previous packaged desktop."""

import os
from pathlib import Path
import stat
import sys
import tempfile
import tomllib


SHARE = Path('/usr/share/gravitas')
PREVIOUS = 'compositor-before-compact-chrome.toml'


def migrate(path, share=SHARE):
    if path.is_symlink() or not path.exists():
        return False
    with os.fdopen(os.open(path, os.O_RDONLY | os.O_NOFOLLOW), 'rb') as stream:
        metadata = os.fstat(stream.fileno())
        if not stat.S_ISREG(metadata.st_mode) or metadata.st_uid != os.geteuid():
            raise ValueError('The compositor config must be a regular file owned by the login user.')
        original = stream.read()
    if original != (share / 'defaults' / PREVIOUS).read_bytes():
        return False
    backup = path.with_name(path.name + '.pre-compact-chrome')
    if backup.exists() or backup.is_symlink():
        return False
    # Later releases can add unrelated defaults. Migrate only the chrome style
    # in this exact historical snapshot, preserving all its other settings.
    changed = original.replace(b'\nstyle = "islands"\n', b'\nstyle = "unified"\n', 1)
    expected = tomllib.loads(original.decode())
    expected['chrome']['style'] = 'unified'
    if tomllib.loads(changed.decode()) != expected:
        raise ValueError('The packaged chrome migration would change unrelated settings.')

    def unchanged():
        latest = path.lstat()
        if (latest.st_dev, latest.st_ino, latest.st_mtime_ns, latest.st_ctime_ns, latest.st_size) != (
                metadata.st_dev, metadata.st_ino, metadata.st_mtime_ns, metadata.st_ctime_ns, metadata.st_size) or path.read_bytes() != original:
            raise RuntimeError('Settings changed during chrome migration; try again at the next login.')

    with tempfile.NamedTemporaryFile(mode='wb', dir=path.parent, delete=False) as stream:
        temporary = Path(stream.name)
        backup_identity = None
        committed = False
        try:
            stream.write(changed)
            stream.flush()
            os.fsync(stream.fileno())
            os.fchmod(stream.fileno(), stat.S_IMODE(metadata.st_mode))
            unchanged()
            try:
                descriptor = os.open(backup, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
            except FileExistsError:
                return False
            with os.fdopen(descriptor, 'wb') as saved:
                saved_metadata = os.fstat(saved.fileno())
                backup_identity = saved_metadata.st_dev, saved_metadata.st_ino
                os.fchmod(saved.fileno(), stat.S_IMODE(metadata.st_mode))
                saved.write(original)
                saved.flush()
                os.fsync(saved.fileno())
            unchanged()
            os.replace(temporary, path)
            committed = True
        finally:
            temporary.unlink(missing_ok=True)
            if backup_identity is not None and not committed:
                latest = backup.lstat()
                if (latest.st_dev, latest.st_ino) == backup_identity:
                    backup.unlink()
    return True


def main():
    path = Path(os.environ.get('XDG_CONFIG_HOME', Path.home() / '.config')) / 'gravitas/compositor.toml'
    try:
        if migrate(path):
            print('Gravitas: enabled compact chrome for the stock desktop; original saved with .pre-compact-chrome.')
    except (OSError, ValueError, RuntimeError) as error:
        print(f'Gravitas chrome migration: {error}', file=sys.stderr)


if __name__ == '__main__':
    main()
