from maenv import MOEAEnv
from maenv_register import Task
from agents import *
import argparse
import numpy as np
import random
import ray
import os

task = Task.get_task(name="all")


def get_args():
    parser = argparse.ArgumentParser()
    #
    parser.add_argument('--adaptive-open', action="store_true", default=False)  # use adaptive Weights
    #
    parser.add_argument('--key', type=str, default='WFG6_3')
    parser.add_argument('--seed', type=int, default=2022)
    parser.add_argument('--population-size', type=int, default=210)
    parser.add_argument('--budget-ratio', type=int, default=100)
    parser.add_argument('--n-ref-points', type=int, default=1000)
    parser.add_argument('--save-history', action="store_true", default=False)
    parser.add_argument('--baseline', action="store_true", default=False)  # use default operator Type
    parser.add_argument('--wo-obs', action="store_true", default=False)  # use adaptive Weights
    parser.add_argument('--early-stop', action="store_true", default=False)
    parser.add_argument('--test', action="store_true", default=False)
    parser.add_argument('--description', type=str, default='test')
    parser.add_argument('--repeat', type=int, default=30)
    parser.add_argument('--alpha', type=float, default=0.1)
    parser.add_argument('--c', type=float, default=1.0)
    args = parser.parse_known_args()[0]
    return args


@ray.remote
def step_in_env(args):
    env = MOEAEnv(key=args.key, population_size=args.population_size, n_ref_points=args.n_ref_points,
                  budget_ratio=args.budget_ratio, save_history=args.save_history, early_stop=args.early_stop,
                  baseline=args.baseline, adaptive_open=args.adaptive_open, wo_obs=args.wo_obs, test=args.test)
    env.reset()
    info = None
    action_value = np.zeros(shape=(4, 4), dtype=np.float64)
    action_count = np.zeros(shape=(4, 4), dtype=np.float64)
    action_count[3, 2:] = np.inf
    is_ter = False
    t = 1
    while not is_ter:
        mask = env.get_avail_actions()
        _action_value = copy.deepcopy(action_value)
        _action_count = copy.deepcopy(action_count)
        _action_count[action_count == 0] = 1
        _action_value += args.c * np.sqrt(np.log(t) / _action_count)

        _action_value[action_count == 0] = np.inf
        _action_value[mask == 0] = -np.inf
        action = np.argmax(_action_value, axis=1)
        rew, is_ter, info = env.step(action)
        rew /= 100
        for i in range(4):
            action_value[i][action[i]] = args.alpha * rew + (1 - args.alpha) * action_value[i][action[i]]
            action_count[i][action[i]] += 1
        t += 1
    return info


def moea_run_baseline(args=get_args()):
    args.save_history = True
    args.wo_obs = True
    save_path = './22data/baseline/mabandit/'
    if not os.path.exists(save_path):
        os.umask(0)
        os.makedirs(save_path, mode=0o777)
    np.random.seed(args.seed)
    random.seed(args.seed)

    info = ray.get([step_in_env.remote(args) for _ in range(args.repeat)])
    np.savez(
        f'{save_path}{args.key}_sd{args.seed}_rp{args.repeat}.npz',
        info_stack=info)


if __name__ == '__main__':
    args = get_args()
    ray.init(num_cpus=args.repeat)
    for t in task:
        args.key = t
        moea_run_baseline(args)
        print("===== Finish" + args.key + " =====")
