%function main(Macro_Bkhaul_Limit,Pico_Bkhaul_Limit)

clear all
Macro_Bkhaul_Limit = 32;
Pico_Bkhaul_Limit = 16;
%num_user = 30;
%debug_mode = 0;

% if debug_mode == 0
%     
%     current_dir = cd;
%     
%     %cd('E:\Dropbox\cvx\');
%     cd('/fs2/comm/wygrp/bdai/cvx/');
%     cvx_setup
%     
%     cd(current_dir);
% end

%simulation parameters
Sim.snr_gap_dB = 9;
Sim.snr_gap = dB2dec(Sim.snr_gap_dB);
Sim.sqr_gap = 2.7;
Sim.sqr_gap_dB = dec2dB(Sim.sqr_gap);
%noise_dBm = [-130 -140 -150 -160];
Sim.noise_dBm = -150;
Sim.noise = dB2dec(Sim.noise_dBm);
Sim.Num_Cell = 7;%total num of cells
Sim.Num_BS = 4; %num base-stations per cell
Sim.Num_Macro = 1; %num macro base-stations
Sim.Num_Pico = 3; %num pico base-stations
Sim.Num_User = 30; %num users per cell
Sim.Num_Ant_Macro = 1; %num ant's per macro BS
Sim.Num_Ant_Pico = 1; %num ant's per pico BS
Sim.Num_Rx_Ant = 1;
Sim.B2Bdist = 0.8; %km
Sim.BW = 10e6;%bandwidth
Sim.P_max_Macro_dBm = 43 - dec2dB(Sim.BW); %dBm/Hz
Sim.P_max_Pico_dBm = 30 - dec2dB(Sim.BW); %dBm/Hz
Sim.MinWMMSEIter = 15; %minimum WMMSE iterations

Power_Mode = 3;
intf_2nd = zeros(Sim.Num_Rx_Ant,Sim.Num_Rx_Ant);
%[Chn, path_loss_dB, dist] = GenHetNetChnSingleCell(Sim);

% Chn_file_name = sprintf('Chn%d_K%d.mat',Chn_idx,K);
% load(Chn_file_name);

load Chn.mat;

% if debug_mode == 0
%     save_file_name = sprintf('/fs2/comm/wygrp/bdai/Results02202015/FullCompression_WMMSE_Macro%d_Pico%d_NumUser%d_Noise%d_New.mat',Macro_Bkhaul_Limit,Pico_Bkhaul_Limit,num_user,noise_idx);
%     save(save_file_name,'Sim');
% end

%Bkhaul_ratio = 4; %the ratio of the amount of backhaul between macro BS and pico BS

%Pico_Bkhaul_Limit = [2 4 6 8];
%Macro_Bkhaul_Limit = Pico_Bkhaul_Limit*Bkhaul_ratio;


Cells = struct([]);
User = struct([]);
BS = struct([]);

for c = 1:Sim.Num_Cell
    for b = 1:Sim.Num_BS
        if b <= Sim.Num_Macro
            BS(c,b).total_power_budget = dB2dec(Sim.P_max_Macro_dBm);
            BS(c,b).total_bkhaul_budget = Macro_Bkhaul_Limit; %Macro_Bkhaul_Limit(Bkhaul_idx);
        else
            BS(c,b).total_power_budget = dB2dec(Sim.P_max_Pico_dBm);
            BS(c,b).total_bkhaul_budget = Pico_Bkhaul_Limit;%Pico_Bkhaul_Limit(Bkhaul_idx);
        end
        
        %BS(c,b).compression_power = 0;
        %BS(c,b).current_compression_bkhaul = 1e10; %some large value
        %BS(c,b).total_bkhaul_budget = Per_BS_Bkhaul_Limit(c,b);
        BS(c,b).quantization_noise = 0;%initial value for sum power computation before backhaul optimization
        BS(c,b).data_sharing_users = [];
    end
end

%initialization
for iCell = 1:Sim.Num_Cell
    for k = 1:Sim.Num_User
        User(iCell,k).long_avg_rate = 1e-3;
        User(iCell,k).avg_rate = 0;
    end
    Cells(iCell).UnScheduled_User = 1:Sim.Num_User;
end

M = 10; %maximum number of serving BSs per User
[User, Asso_User] = Neighbour(Sim, Sim.Num_Cell, Sim.Num_User, path_loss_dB, BS,User,M,Sim.noise_dBm);

out_iter = 1;
%previous_utility = 1;
%current_utility = 2;
Log_Data = struct([]);
Num_Scheduled_User = 4;
%%
tic;
while out_iter <= 1
    %abs((current_utility - previous_utility)/current_utility) > 1e-2 || out_iter <=70
    tic;
%    previous_utility = current_utility;
    fprintf('$$$$$$ User Scheduling iter = %d $$$$$$$ \n', out_iter);
    %User scheduler
%     for iCell = 1:Sim.Num_Cell
%         [Cells(iCell).Scheduled_User, Cells(iCell).UnScheduled_User]= Round_Robin(Cells(iCell).UnScheduled_User,Num_Scheduled_User);
%         
%         %         Log_Data(out_iter).Cells(iCell).Scheduled_User = Cells(iCell).Scheduled_User;
%         %         Log_Data(out_iter).Cells(iCell).UnScheduled_User = Cells(iCell).UnScheduled_User; % log user scheduling
%         if isempty(Cells(iCell).UnScheduled_User)
%             Cells(iCell).UnScheduled_User = 1:Sim.Num_User;
%         end
%     end
    
Cells(1).Scheduled_User = [8 11 12 19];
Cells(2).Scheduled_User = [3 7 21 30];
Cells(3).Scheduled_User = [6 12 19 28];
Cells(4).Scheduled_User = [3 6 13 27];
Cells(5).Scheduled_User = [13 16 19 21];
Cells(6).Scheduled_User = [7 9 13 24];
Cells(7).Scheduled_User = [2 4 24 27];

Cells(1).UnScheduled_User = [1     2     3     4     5     6     7     9    10    13    14    15    16    17    18    20    21    22    23    24    25    26    27    28    29    30];
Cells(2).UnScheduled_User = [1     2     4     5     6     8     9    10    11    12    13    14    15    16    17    18    19    20    22    23    24    25    26    27    28    29];
Cells(3).UnScheduled_User = [1     2     3     4     5     7     8     9    10    11    13    14    15    16    17    18    20    21    22    23    24    25    26    27    29    30];
Cells(4).UnScheduled_User = [1     2     4     5     7     8     9    10    11    12    14    15    16    17    18    19    20    21    22    23    24    25    26    28    29    30];
Cells(5).UnScheduled_User = [1     2     3     4     5     6     7     8     9    10    11    12    14    15    17    18    20    22    23    24    25    26    27    28    29    30];
Cells(6).UnScheduled_User = [1     2     3     4     5     6     8    10    11    12    14    15    16    17    18    19    20    21    22    23    25    26    27    28    29    30];
Cells(7).UnScheduled_User = [1     3     5     6     7     8     9    10    11    12    13    14    15    16    17    18    19    20    21    22    23    25    26    28    29    30];
    
    Num_Serving_User = zeros(Sim.Num_Cell,Sim.Num_BS); %num of users each BS supports at the begining
    for iCell = 1:Sim.Num_Cell
        for ik = 1:length(Cells(iCell).Scheduled_User)
            k = Cells(iCell).Scheduled_User(ik);
            User(iCell,k).ServingAnt = 0;
            User(iCell,k).chn = Get_Chn(Chn,User(iCell,k).ServingCluster,iCell,k,Sim);
            for iBS = 1:size(User(iCell,k).ServingCluster,1)
                
                curr_cell = User(iCell,k).ServingCluster(iBS,1);
                curr_BS = User(iCell,k).ServingCluster(iBS,2);
                User(iCell,k).bkhaul_wgt(curr_cell,curr_BS) = 0.01;
                Num_Serving_User(curr_cell,curr_BS) = Num_Serving_User(curr_cell,curr_BS) + 1;
                
                if curr_BS <= Sim.Num_Macro %Macro BS
                    User(iCell,k).ServingAnt = User(iCell,k).ServingAnt + Sim.Num_Ant_Macro;
                else
                    User(iCell,k).ServingAnt = User(iCell,k).ServingAnt + Sim.Num_Ant_Pico;
                end
            end
        end
    end
    
    %Initialize wgts
    max_wgt = 0;
    for iCell = 1:Sim.Num_Cell
        for ik = 1:length(Cells(iCell).Scheduled_User)
            k = Cells(iCell).Scheduled_User(ik);
            User(iCell,k).wgt_wsr = 1/User(iCell,k).long_avg_rate;
            User(iCell,k).prev_inst_rate = 0.01;
            if User(iCell,k).wgt_wsr > max_wgt
                max_wgt = User(iCell,k).wgt_wsr;
            end
        end
    end
    %normalize user wgts by max_wgt
    for iCell = 1:Sim.Num_Cell
        for ik = 1:length(Cells(iCell).Scheduled_User)
            k = Cells(iCell).Scheduled_User(ik);
            User(iCell,k).wgt_wsr = User(iCell,k).wgt_wsr/max_wgt;
            
        end
    end
    
    % initialize TX beamformers and sparse Matrix
    for l = 1:Sim.Num_Cell
        for kk = 1:length(Cells(l).Scheduled_User)
            k = Cells(l).Scheduled_User(kk); %scheduled user in cell l
            Num_ServingAnt = User(l,k).ServingAnt;
            temp_tx = randn(Num_ServingAnt,1) + 1i*randn(Num_ServingAnt,1);
            
            ant_head = 1;
            temp_tx2 = [];
            for m = 1:size(User(l,k).ServingCluster,1)
                
                curr_cell = User(l,k).ServingCluster(m,1);
                curr_BS = User(l,k).ServingCluster(m,2);
                if curr_BS <= Sim.Num_Macro
                    Num_Tx_Ant = Sim.Num_Ant_Macro;
                else
                    Num_Tx_Ant = Sim.Num_Ant_Pico;
                end
                ant_tail = ant_head + Num_Tx_Ant - 1;
                norm_tx = temp_tx(ant_head:ant_tail)/norm(temp_tx(ant_head:ant_tail));
                
                norm_factor = Sim.sqr_gap/(2^BS(curr_cell,curr_BS).total_bkhaul_budget - 1) + 1;
                temp_tx2 = [temp_tx2;sqrt(BS(curr_cell,curr_BS).total_power_budget/Num_Serving_User(curr_cell,curr_BS)/norm_factor)*norm_tx];
                ant_head = ant_tail+1;
                User(l,k).BS_Power(m) = BS(curr_cell,curr_BS).total_power_budget/Num_Serving_User(curr_cell,curr_BS);
            end
            
            User(l,k).beam_tx = temp_tx2;
            if length(User(l,k).beam_tx) ~= User(l,k).ServingAnt
                fprintf('$$$ Tx Initialization Not Right $$$ \n');
            end
        end
    end
    
    
    for c = 1:Sim.Num_Cell
        for b = 1:Sim.Num_BS
            BS(c,b).current_compression_bkhaul = BS(c,b).total_bkhaul_budget;%BS(c,b).current_min_compression_bkhaul;
            BS(c,b).quant_wgt = Sim.sqr_gap/(2^BS(c,b).total_bkhaul_budget - 1);
        end
    end
    
    [~,per_BS_power,User,~,BS] = Sum_Power(Sim.Num_Cell,Cells,User,Sim.Num_Macro,Sim.Num_Pico,Sim.Num_Ant_Macro,Sim.Num_Ant_Pico,BS);
    
    %inner iteration
  %  inner_iter = 1;
  %  inner_pre_iter_wsr = 1;
  %  while 1>0
%        fprintf('\n $$$$$ Iteration = %d  $$$$$$\n',inner_iter);
               
        %define the constant parameters to be used in optimizing the bf's
        [User, BS] = parameter_def_bf_optimize(User,Cells,BS,Sim,Chn);
        
        %WMMSE approach to optimize bf's
        [User,sumrate, wgt_sumrate, Per_BS_Bkhaul, Cells, BS] = WSR_Solver_WMMSE(Cells,User,Chn,Sim,intf_2nd,Power_Mode,BS);
               
%          if abs(inner_pre_iter_wsr - wgt_sumrate) < 1e-2
%              break;
%          else
%              inner_pre_iter_wsr = wgt_sumrate;
%          end
%         
%         inner_iter = inner_iter + 1;
%         
%     end
    
    Log_Data(out_iter).Per_BS_Bkhaul = Per_BS_Bkhaul;
    
    [Log_Utility,User,Log_Data] = Compute_Utility(Sim.Num_Cell,Sim.Num_User,User,Cells,BS,out_iter,Sim.Num_BS,Log_Data);
    
    fprintf('$$$$ Current Log Utility = %f $$$$ \n\n\n\n',Log_Utility);
    
%    current_utility = Log_Utility;
    out_iter = out_iter + 1;
    
%     if debug_mode == 0
%         save(save_file_name, 'Log_Data', 'User', 'BS', 'Cells');
%     end
    toc;
end
toc;