classdef SupplyChain < handle
    % SUPPLYCHAIN Main results describing the supply chain. 
    %   
    %
    
    properties
                
    end
    
    properties ( SetAccess = private , Hidden = false )
    
        Parent
                 
    end
    
    properties (Dependent = true, SetAccess = private)
       
        
    end
    
    methods
        
        function obj = SupplyChain( MyParent )
            % Constructor that tracks what type of parent object has
            obj.Parent = MyParent;            
                        
        end
        
        % Methods used to calculate the supply chain descriptive results
        
        function [ VA , M , VA_Dom ] = BackwardRequirements( obj , FD , s )
           
           NoInd = obj.Parent.Settings.NoIndustries;
           Ab = obj.Parent.Matrices.Ab;
           Ab_Dom = obj.Parent.Matrices.Ab_Dom;
           Bb = obj.Parent.Matrices.Bb;
           Bb_Dom = obj.Parent.Matrices.Bb_Dom;
           
           if ( s == 0 )
              
               BSR = Ab*inv( eye(size(Ab,1)) - Ab )*Bb*FD;
               BSR_Dom = Ab_Dom*inv( eye(size(Ab_Dom,1)) - Ab_Dom )*Bb_Dom*FD;
               
           else
               
               BSR = Ab*( eye(size(Ab,1)) - Ab^s )*inv( eye(size(Ab,1)) - Ab )*Bb*FD;
               BSR_Dom = Ab_Dom*( eye(size(Ab_Dom,1)) - Ab^s )*inv( eye(size(Ab_Dom,1)) - Ab_Dom )*Bb_Dom*FD;
               
           end
            
           % Extracting the vectors of interest
           VA = BSR( (2.*NoInd+1):(3.*NoInd) , 1 );
           M  = BSR( (3.*NoInd+1):(4.*NoInd) , 1 );
           VA_Dom = BSR_Dom( (2.*NoInd+1):(3.*NoInd) , 1 );
           
        end
        
        function [ VA , M , FD , VA_Dom , FD_Dom] = ForwardRequirements( obj , VA , M , s )
           
           NoInd = obj.Parent.Settings.NoIndustries;
           Af = obj.Parent.Matrices.Af;
           Af_Dom = obj.Parent.Matrices.Af_Dom;
           Bf = obj.Parent.Matrices.Bf;
           Bf_Dom = obj.Parent.Matrices.Bf_Dom;
           Y0 = [ VA ; M , zeros( NoInd , 1 ) ];
           Y0_Dom = [ VA ; zeros( NoInd , 1 ) ];
           
           if ( s == 0 )
              
               FSR = Af*inv( eye(size(Af,1)) - Af )*Y0;
               FSR_Dom = Af_Dom*inv( eye(size(Af_Dom,1)) - Af_Dom )*Y0_Dom;
               
           else
               
               FSR = Ab*( eye(size(Af,1)) - Af^s )*inv( eye(size(Af,1)) - Af )*Y0;
               FSR_Dom = Af_Dom*( eye(size(Af_Dom,1)) - Af^s )*inv( eye(size(Af_Dom,1)) - Af_Dom )*Y0_Dom;
               
           end
            
           % Extracting the vectors of interest
           VA = FSR( 1:NoInd , 1 );
           M  = FSR( (NoInd+1):(2.*NoInd) , 1 );
           FD = FSR( (2.*NoInd+1):(3.*NoInd) , 1 );
           VA_Dom = FSR_Dom( 1:NoInd , 1 );
           FD_Dom = FSR_Dom( (NoInd+1):(2.*NoInd) , 1 );
          
        end
        
        function [ Forward , Forward_Dom , Backward , Backward_Dom ] = Length( obj ) 
        % Calculates the expected number of steps along the supply chain
        % that a dollar travels
        
           NoInd = obj.Parent.Settings.NoIndustries;
           Af = obj.Parent.Matrices.Af;
           Af_Dom = obj.Parent.Matrices.Af_Dom;
           Ab = obj.Parent.Matrices.Ab;
           Ab_Dom = obj.Parent.Matrices.Ab_Dom; 
            
           TotalForward = Af*inv(eye(size(Af,1))-Af);
           TotalForward_Dom = Af_Dom*inv(eye(size(Af_Dom,1))-Af_Dom);
           TotalBackward = Ab*inv(eye(size(Ab,1))-Ab);
           TotalBackward_Dom = Ab_Dom*inv(eye(size(Ab_Dom,1))-Ab_Dom);
           
           SumsForward = inv(eye(size(Af,1))-Af)*(Af+Af*TotalForward);
           SumsForward_Dom = inv(eye(size(Af_Dom,1))-Af_Dom)*...
                                (Af_Dom+Af_Dom*TotalForward_Dom);
           SumsBackward = inv(eye(size(Ab,1))-Ab)*(Ab+Ab*TotalBackward);
           SumsBackward_Dom = inv(eye(size(Ab_Dom,1))-Ab_Dom)*...
                                (Ab_Dom+Ab_Dom*TotalBackward_Dom);
           
           Forward = (SumsForward'*[zeros(2.*NoInd,1);ones(NoInd,1)])./ ...
                     (TotalForward'*[zeros(2.*NoInd,1);ones(NoInd,1)]);
           Forward(isnan(Forward)) = 0;
           Forward_Dom = (SumsForward_Dom'*[zeros(NoInd,1);ones(NoInd,1)])./ ...
                         (TotalForward_Dom'*[zeros(NoInd,1);ones(NoInd,1)]);
           Forward_Dom(isnan(Forward_Dom)) = 0;
           Backward = (SumsBackward'*[zeros(2.*NoInd,1);ones(2.*NoInd,1)])./ ...
                      (TotalBackward'*[zeros(2.*NoInd,1);ones(2.*NoInd,1)]);
           Backward(isnan(Backward)) = 0 ;
           Backward_Dom = (SumsBackward_Dom'*[zeros(2.*NoInd,1);ones(NoInd,1)])./ ...
                          (TotalBackward_Dom'*[zeros(2.*NoInd,1);ones(NoInd,1)]);  
           Backward_Dom(isnan(Backward_Dom)) = 0;
                     
        end
    end
    
end

