import os
import sys
import time
import logging
from collections import namedtuple

import megengine as mge
import megengine.distributed as dist
import megengine.functional as F
import megengine.autodiff as autodiff
import megengine.optimizer as optim

import yaml
from tensorboardX import SummaryWriter

from nets import Model
from dataset import CREStereoDataset
from megengine.data import DataLoader, RandomSampler, Infinite


def parse_yaml(file_path: str) -> namedtuple:
    """Parse yaml configuration file and return the object in `namedtuple`."""
    with open(file_path, "rb") as f:
        cfg: dict = yaml.safe_load(f)
    args = namedtuple("train_args", cfg.keys())(*cfg.values())
    return args


def format_time(elapse):
    elapse = int(elapse)
    hour = elapse // 3600
    minute = elapse % 3600 // 60
    seconds = elapse % 60
    return "{:02d}:{:02d}:{:02d}".format(hour, minute, seconds)


def ensure_dir(path):
    if not os.path.exists(path):
        os.makedirs(path, exist_ok=True)


def adjust_learning_rate(optimizer, epoch):

    warm_up = 0.02
    const_range = 0.6
    min_lr_rate = 0.05

    if epoch <= args.n_total_epoch * warm_up:
        lr = (1 - min_lr_rate) * args.base_lr / (
            args.n_total_epoch * warm_up
        ) * epoch + min_lr_rate * args.base_lr
    elif args.n_total_epoch * warm_up < epoch <= args.n_total_epoch * const_range:
        lr = args.base_lr
    else:
        lr = (min_lr_rate - 1) * args.base_lr / (
            (1 - const_range) * args.n_total_epoch
        ) * epoch + (1 - min_lr_rate * const_range) / (1 - const_range) * args.base_lr

    optimizer.param_groups[0]["lr"] = lr


def sequence_loss(flow_preds, flow_gt, valid, gamma=0.8):

    n_predictions = len(flow_preds)
    flow_loss = 0.0

    for i in range(n_predictions):
        i_weight = gamma ** (n_predictions - i - 1)
        i_loss = F.abs(flow_preds[i] - flow_gt)
        flow_loss += i_weight * (F.expand_dims(valid, axis=1) * i_loss).mean()

    return flow_loss


def main(args):
    # initial info
    mge.random.seed(args.seed)
    rank, world_size = 
dist.get_rank()