# 用于提供对外接口
from base_optimizer.smopt_scanbased import *
from base_optimizer.smopt_celldivision import *
from base_optimizer.smopt_hybridgenetic import *
from base_optimizer.smopt_feederpriority import *
from base_optimizer.smopt_aggregation import *
from base_optimizer.smopt_twophase import *
from base_optimizer.smopt_mathmodel import *
from base_optimizer.smtopt_route import *

from base_optimizer.result_analysis import *


def base_optimizer(machine_index, pcb_data, component_data, feeder_data, params, hinter=False):

    if params.machine_optimizer == 'cell-division':  # 基于元胞分裂的遗传算法
        component_result, cycle_result, feeder_slot_result = optimizer_celldivision(pcb_data, component_data)
        placement_result, head_sequence = place_allocate_sequence_route_generation(component_data, pcb_data,
                                                                                   component_result, cycle_result,
                                                                                   feeder_slot_result)
    elif params.machine_optimizer == 'feeder-priority':  # 基于基座扫描的供料器优先算法
        component_result, cycle_result, feeder_slot_result = feeder_priority_assignment(component_data, pcb_data,
                                                                                        feeder_data)
        placement_result, head_sequence = scan_based_placement_route_generation(component_data, pcb_data,
                                                                                   component_result, cycle_result,
                                                                                   feeder_slot_result)
    elif params.machine_optimizer == 'hybrid-genetic':  # 基于拾取组的混合遗传算法
        component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = optimizer_hybrid_genetic(
            pcb_data, component_data, hinter=hinter)

    elif params.machine_optimizer == 'aggregation':  # 基于batch-level的整数规划 + 启发式算法
        component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = optimizer_aggregation(
            component_data, pcb_data, hinter=hinter)
    elif params.machine_optimizer == 'genetic-scanning':
        component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = optimizer_genetic_scanning(
            component_data, pcb_data, hinter=hinter)
    elif params.machine_optimizer == 'mip-model':
        component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = optimizer_mathmodel(
            component_data, pcb_data, hinter=hinter)
    elif params.machine_optimizer == "two-phase":
        component_result, feeder_slot_result, cycle_result = gurobi_optimizer(pcb_data, component_data, feeder_data,
                                                                              initial=True, partition=False,
                                                                              reduction=True, hinter=hinter)

        placement_result, head_sequence = place_allocate_sequence_route_generation(component_data, pcb_data,
                                                                                   component_result, cycle_result,
                                                                                   feeder_slot_result)
    else:
        raise 'machine optimizer method ' + params.method + ' is not existed'

    # print('----- Placement machine ' + str(machine_index) + ' ----- ')
    opt_res = OptResult(component_result, cycle_result, feeder_slot_result, placement_result, head_sequence)
    # 估算贴装用时
    info = placement_info_evaluation(component_data, pcb_data, opt_res, hinter=False)
    if hinter:
        optimization_assign_result(component_data, pcb_data, opt_res, nozzle_hinter=True, component_hinter=True,
                                   feeder_hinter=True)
        info.print()
        print('------------------------------ ')

    # placement_route_schematic(pcb_data, component_data, opt_res, 1)
    if params.save:
        output_optimize_result(
            f'result/{params.filename[:-4]}-{params.line_optimizer}-M0{machine_index} {params.save_suffix}',
            component_data, pcb_data, opt_res)

    # output_optimize_result(f'{params.filename[:-4]}', component_data, pcb_data, opt_res)

    return info
