#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys

import xmir_base
import gateway
from gateway import die
import read_info


if len(sys.argv) <= 1:
  die("Bootloader name not specified!")
bl_name = sys.argv[1]
bl_name = bl_name.strip().lower()


gw = gateway.Gateway()
dn = gw.device_name
if not gw.device_name:
  die("Xiaomi Mi Wi-Fi device not found! (IP: {})".format(gateway.ip_addr))

fn_dir    = 'bootloader/'
fn_remote = '/tmp/bootloader.bin'
fn_local  = None

if bl_name == 'breed':
  supported_devices = ['R3G', 'R3P', 'RM2100', 'RA71', 'CR6606', 'CR6608', 'CR6609', 'TR609', 'TR608']
  if dn not in supported_devices:
    die("Breed bootloader cannot be installed on this device!")
  if dn in ['CR6606', 'CR6608', 'CR6609', 'TR609', 'TR608']:
    fn_local = fn_dir + 'pb-boot-cr660x.img'
  else:
    fn_local = fn_dir + 'breed_r3g_eng.bin'

if bl_name == 'uboot':
  # Check if device has a specific uboot file available
  supported_uboot_devices = ['R3G', 'R3P', 'RM2100']
  if dn not in supported_uboot_devices:
    die("U-Boot bootloader is not available for this device! Supported devices: {}".format(', '.join(supported_uboot_devices)))
  fn_local = fn_dir + 'uboot_{}.bin'.format(dn.lower())

if not fn_local:
  die('Incorrect bootloader name!')

if not os.path.exists(fn_local):
  die('File "{}" not found'.format(fn_local))

dev = read_info.DevInfo(verbose = 0, infolevel = 1)
if dev.info.cpu_arch != 'mips':
  die("Currently support only MIPS arch!")

dev.get_bootloader()
if not dev.bl.img:
  die("Can't dump current bootloader!")

if dev.bl.spi_rom:
  die("Not support SPI Flash ROM! (now supported only NAND)")

addr = None
name = None
size = None

# Find bootloader partition (typically at address 0, but skip large "ALL" partitions)
for p, part in enumerate(dev.partlist):
  if part['addr'] == 0 and part['size'] > 0x00800000:  # 8MiB
    continue  # skip "ALL" part
  if part['addr'] == 0:
    name = part['name']
    fname = ''.join(e for e in name if e.isalnum())
    addr = part['addr']
    size = part['size']
    break  # Take the first valid partition found

if addr is None:
  die("No matching partition found!")

# Validate that we have a proper partition name before proceeding
if not name:
  die("Invalid partition name found!")

print('Selected partition: "{}" at address 0x{:08X} (size: 0x{:08X})'.format(name, addr, size))

# Upload bootloader file to device
try:
  gw.upload(fn_local, fn_remote)
except Exception as e:
  die('Failed to upload bootloader file: {}'.format(str(e)))

print('Writing data to partition "{}" (addr: {}) ...'.format(name, "0x%08X" % addr))

# Write bootloader to partition with error handling
try:
  gw.run_cmd('mtd write {bin} "{name}"'.format(bin=fn_remote, name=name))
except Exception as e:
  die('Failed to write bootloader to partition: {}'.format(str(e)))

print('Ready! Bootloader "{}" installation is complete.'.format(bl_name))
