function [BSL,BSR,dt_array,dI_array,Unmodified_DI_array,Final_level_pts,std_list,level_type] =Level_Reconstruction_Light(I_data,I_fit,time_data,dt_array,dI_array,iterations,true_levels,cutoff_pts,end_to_end_cutoff_pts,min_allowed_delta_I,I_PDC,smooth_fac)

%Initializing Arrays
event_length=size(I_data,1);
padded_level_pts=sort([1;true_levels;event_length]);%padding is done for the ease of accounting for the baseline points later in the for loop
starting_levels=size(padded_level_pts,1)-1;
level_type=ones(length(dI_array),1);

jj=0;
ending_levels=starting_levels-1;
            current_diff=abs(min(diff(dI_array)));
            if isempty(current_diff)==1%now we have a single level event
                current_diff=2*min_allowed_delta_I;%this is such that the outer while loop gets terminated with single level events
            end

while (starting_levels>ending_levels||jj==1||current_diff<min_allowed_delta_I) && jj<=iterations
        jj=jj+1;
        
        starting_levels=length(padded_level_pts)-1;
        levels=starting_levels;
        
        i=2;%Starting from the first event
        itr_next=i+1;
        itr_prev=i-1;
        
    while i<=levels-1 && levels>=3 && itr_next<=length(I_fit)
       
       t_data=time_data(padded_level_pts(i):padded_level_pts(i+1));
       I_array=I_data(padded_level_pts(i):padded_level_pts(i+1));
       sub_event_size=size(t_data,1);
               
       current_level_mean=I_fit(i);
       previous_mean=I_fit(itr_prev);
       next_mean=I_fit(itr_next);
       
            if current_level_mean<previous_mean && current_level_mean<next_mean
               %downward pulse like event
                current_mean=Level_Mean_Universal(I_array);
                peak_count=1;
                LT=1;%Level Type
                
           elseif current_level_mean>previous_mean && current_level_mean>next_mean %upwards. These are typically sharp
                %upward pulse like event
                current_mean=Level_Mean_Universal(I_array); 
                peak_count=1;
                LT=2;%Level Type
           else
                %intermediate level rather than a peak or a valley
                LT=3;%Level Type
                current_mean=Level_Mean_Universal(I_array);
                if sum(dt_array)<end_to_end_cutoff_pts
                    sm_I_data=smoothdata(I_array,'movmean',2);
                    peak_count=level_crossing_count_Edges_MOD(sm_I_data,I_PDC,smooth_fac);
                else
                    peak_count=level_crossing_count_Edges_MOD(I_array,I_PDC,smooth_fac);
                end
            end
               
                %Saving the Data
                delta_I_next=abs(current_mean-next_mean);
                delta_I_previos=abs(current_mean-previous_mean);
                               
                if (i==2||i==levels-1) %first and last level logics that are not downward sub-events
                   lvl_logic=delta_I_next>min_allowed_delta_I && current_mean<I_PDC && peak_count>0;
                else
                    lvl_logic=delta_I_next>min_allowed_delta_I && peak_count>0;
                end
                
           if delta_I_next<delta_I_previos
               
                        if lvl_logic==1 || jj==1 %you let the first run pass to get the optimal level means
                                                       
                            I_fit(i)=current_mean;
                            dt_array(i-1)=sub_event_size;
                            dI_array(i-1)=current_mean;
                            level_type(i-1)=LT;
                            
                            i=i+1;
                            itr_next=i+1;
                            itr_prev=i-1;
                            
                        else
                                
                            padded_level_pts(i+1)=[];  
                            levels=size(padded_level_pts,1)-1; 
                            I_fit(i)=[];
                            dt_array(i-1)=[];
                            dI_array(i-1)=[];
                            level_type(i-1)=[];
                        end 
           else
               
                        if lvl_logic==1 || jj==1 %you let the first run pass to get the optimal level means
                            
                            I_fit(i)=current_mean;
                            dt_array(i-1)=sub_event_size;
                            dI_array(i-1)=current_mean;
                            level_type(i-1)=LT;
                            
                            i=i+1;
                            itr_next=i+1;
                            itr_prev=i-1;
                            
                        else
                            
                            padded_level_pts(i)=[];  
                            levels=size(padded_level_pts,1)-1; 
                            I_fit(i)=[];
                            dt_array(i-1)=[];
                            dI_array(i-1)=[];
                            level_type(i-1)=[];
                        end 
           end  
    end
        ending_levels=size(padded_level_pts,1)-1;
        current_diff=abs(min(diff(dI_array)));
            if isempty(current_diff)==1%now we have a single level event
                current_diff=2*min_allowed_delta_I;%this is such that the outer while loop gets terminated with single level events
            end
end
   %Now we further refine the level mean values based on thier length
   Unmodified_DI_array=dI_array;
   max_dI=max(dI_array);
   padded_dI_array=[(2*max_dI);dI_array';(2*max_dI)];%2*max_I is just a placeholder that represent baseline by saying that it is higher than any other level
   levels_to_refine=length(padded_dI_array);
   refined_padded_level_pts=sort(unique(padded_level_pts));
   for i=2:levels_to_refine-1
       I_array=I_data(refined_padded_level_pts(i):refined_padded_level_pts(i+1));
       sub_event_size=dt_array(i-1);
       current_level_mean=padded_dI_array(i);
       previous_mean=padded_dI_array(i-1);
       next_mean=padded_dI_array(i+1);
            if current_level_mean<previous_mean && current_level_mean<next_mean
               %downward pulse like event
               if sub_event_size<cutoff_pts
                    mean_data=mean(I_array);
                    prel_data=I_array(I_array<mean_data);
                    dI_array(i-1)=weighted_mean(prel_data);
               end
                
            elseif current_level_mean>previous_mean && current_level_mean>next_mean %upwards. These are typically sharp
                %upward pulse like event
                if sub_event_size<cutoff_pts
                    mean_data=mean(I_array);
                    prel_data=I_array(I_array>mean_data);
                    dI_array(i-1)=weighted_mean_upward(prel_data);
                end
            end
   end
   
   Final_level_pts=unique(padded_level_pts(2:end-1));
      
   % level goodness based on STD
   total_levels=length(dI_array);
   std_list=zeros(total_levels,1);
   [~,max_dt_index]=max(dt_array);
   I_array=I_data(Final_level_pts(max_dt_index):Final_level_pts(max_dt_index+1));
   sub_event_size=length(I_array);
   [~,Level_STD,~] = Level_STD_Comp(I_array,sub_event_size);
   
   if total_levels>=2 %a minimum of two levels are required for this comparision
        for i=1:total_levels-1
            std_f=3;
            next_mean=dI_array(i+1);
            current_mean=dI_array(i);
                if (next_mean>(current_mean-std_f*Level_STD) && next_mean<(current_mean+std_f*Level_STD))
                    std_rejection=1;
                else
                    std_rejection=0;
                end
            std_list(i)=std_rejection;
        end
   end
   %End of refining
     
   %Adjusting the start and end event end points further
   
       [start_index,end_index]=End_point_Adjustment(I_data,I_fit,Final_level_pts);
       Final_level_pts(1)=start_index;
       Final_level_pts(end)=end_index;
           if length(Final_level_pts)>=2
               dt_array(1)=Final_level_pts(2)-Final_level_pts(1);
               dt_array(end)=Final_level_pts(end)-Final_level_pts(end-1);
           end
   
   %left_baseline
   %event_starting_index=Final_level_pts(1);
   event_starting_index=start_index;
   I_array=I_data(1:event_starting_index-1);
   BSL=weighted_mean(I_array);
      
   %right_baseline
   %event_ending_index=Final_level_pts(end);
   event_ending_index=end_index;
   I_array=I_data(event_ending_index+1:end);
   BSR=weighted_mean(I_array);
   
end
