function d_out = processfile(infile, type, varargin)
%PROCESSFILE converts base and gpm labeled data into qpm labeled data along
%with a few data transformations
%   infile: specifies the file location eg. 'data\Sept_MPC_coremodel.csv'
%   type:   is either 'assumptions', 'base', 'dim', or 'gpm'
%   there are three optional arguments:
%       limit: limits the output database to a given date range
%       dbadd: adds the specified database to the output database
%       other: is a x-by-2 cell array of additional series to be extracted

other = {};

if ~isempty(varargin)
    for i = 1:2:length(varargin)
        switch varargin{i}
            case 'limit='
                limit = varargin{i+1};
            case 'dbadd='
                d_out = varargin{i+1};
            case 'other='
                other = varargin{i+1};
        end
    end
end
        
if strcmp(type,'assumptions')
    %% load the assumptions database
    d_in = dbload(infile);
    
    % map of names from their original names (col 2) to the QPM names
    map = {'oil'  , 'BRENT'    ; ...
        'food'    , 'WFOOD08'  ; ...
        'gdp_bar' , 'GDPOT6'   ; ...
        'gdp_pot' , 'GDPOTGG6' ;...
        'forcmd'  , 'FORCMD'   ;...
        'x_gdp'   , 'WGDP'     };
    
    % append user added series' to the name map
    map = [map; other];
    
    % rebase world food to 2010 
    d_in.WFOOD08 = d_in.WFOOD08 / mean(d_in.WFOOD08(qq(2010,1):qq(2010,4)));
    
    % map and limit all series to the specified range (if specified)
    if exist('limit','var')
        for i = 1:numel(map)/2
            d_out.(map{i,1}) =  d_in.(map{i,2}){limit};
        end
    else
        for i = 1:numel(map)/2
            d_out.(map{i,1}) =  d_in.(map{i,2});
        end
    end
else
    if strcmp(type,'base')
        %% load the base data database
        d_in = dbload(infile);
        
        % map of names from their original names (col 2) to the QPM names
        map = {'cpi_statssa', 'CPITD08'    ; ...
            'cpi_ber'    , 'INFB2D'     ; ...
            'w'          , 'SALAV5'     ; ...
            'emp'        , 'EMPLO5'     ; ...
            'gdp'        , 'GDPMP6'     ; ...
            'rn'         , 'REPORI'     ; ...
            'zarusd'     , 'EXDOLLD'    ; ...
            's_zar'      , 'EXDOLLD'    ; ...
            'rn10'       , 'LBONDI'     };
        
        % append user added series' to the name map
        map = [map; other];
        
        % map and limit all series to the specified range (if specified)
        if exist('limit','var')
            for i = 1:numel(map)/2
                d_out.(map{i,1}) =  d_in.(map{i,2}){limit};
            end
        else
            for i = 1:numel(map)/2
                d_out.(map{i,1}) =  d_in.(map{i,2});
            end
        end
    else
        if strcmp(type,'dim')
            %% load the DIM database
            d_in = dbload(infile);
            
            % map of names from their original names (col 2) to the QPM names
            map = {'bfp_u'       , 'BFP'                ; ...
                'pettax_u'       , 'PETAX'              ; ...
                'petrol'       , 'PETPRICE'           ; ...
                'w_bfp'        , 'WEIGHT_BFP'         ; ...
                'cpi_serv_u'   , 'SERVICES'           ; ...
                'cpi_goodsx_u' , 'GOODSX'             ; ...
                'cpi_elec_u'   , 'ELECTRICITY'        ; ...
                'cpi_petr_u'   , 'PETROLDIESEL'       ; ...
                'cpi_prfn_u'   , 'PARAFFIN'           ; ...
                'cpi_u'        , 'CPI'                ; ...
                'cpi_core_u'   , 'CPIXFEP1'           ; ...
                'cpi_food_u'   , 'FOOD'               ; ...
                'w_serv'       , 'WEIGHT_SERVICES'    ; ...
                'w_goodsx'     , 'WEIGHT_GOODSX'      ; ...
                'w_food'       , 'WEIGHT_FOOD'        ; ...
                'w_elec'       , 'WEIGHT_ELECTRICITY' ; ...
                'w_petr'       , 'WEIGHT_PETROLDIESEL' };
            %             'cpi_food_u'   , 'FOOD'               ; ...
            
            % append user added series' to the name map
            map = [map; other];
            
            % adjust weights
            d_in.WEIGHT_FOOD         = d_in.WEIGHT_FOOD/100        ;
            d_in.WEIGHT_ELECTRICITY  = d_in.WEIGHT_ELECTRICITY/100 ;
            d_in.WEIGHT_PETROLDIESEL = d_in.WEIGHT_PETROLDIESEL/100;
            d_in.WEIGHT_GOODSX       = d_in.WEIGHT_GOODSX/100      ;
            d_in.WEIGHT_SERVICES     = d_in.WEIGHT_SERVICES/100    ;

            % map and limit all series to the specified range (if specified)
            if exist('limit','var')
                for i = 1:numel(map)/2
                    d_out.(map{i,1}) =  d_in.(map{i,2}){limit};
                end
            else
                for i = 1:numel(map)/2
                    d_out.(map{i,1}) =  d_in.(map{i,2});
                end
            end
        else
            if strcmp(type,'gpm')
                %% load the GPM database
                d_in = dbload(infile);
                
                % map of names from their original names (col 2) to the QPM names
                map = {'x_cpi'       ,   'NA'                 ; ...
                    'x_rn'           ,   'RS_G3'                 ; ...
                    's'              ,   'NA'                 ; ...
                    'ls_eur'     ,   'L_S_EZ'           ; ...
                    'ls_jpy'     ,   'L_S_JP'           ; ...
                    'lx_gdp_gap'     ,   'L_GDP_GAP_WRLD'             ; ...
%                     'dot_x_gdp'      ,   'GROWTH_WRLD'        ; ...
                    'dot_x_gdp_eq'   ,   'DLA_GDP_BAR_WRLD'    ; ...
                    'g_x'            ,   'G_GDP_BAR_WRLD'            };
                
                % append user added series' to the name map
                map = [map; other];
                
                % weight foreign cpi according to trade weights
                x = exp(d_in.('L_CPI_EZ'){limit} / 100);
                y = exp(d_in.('L_CPI_JP'){limit} / 100);
                z = exp(d_in.('L_CPI_US'){limit} / 100);
                
                x_cpi_u = (0.244 * (x / mean(x(qq(2010,1):qq(2010,4))))   +  ...
                    0.100 * (y / mean(y(qq(2010,1):qq(2010,4))))   +  ...
                    0.124 * (z / mean(z(qq(2010,1):qq(2010,4)))) ) / ...
                    (0.244 + 0.100 + 0.124);
                x_cpi_u = x_cpi_u / mean(x_cpi_u(qq(2010,1):qq(2010,4))) * 100 ;
                d_out.(map{find(strcmp(map(:,1),'x_cpi')),1}) = x_cpi_u;
                
                % weight foreign interest rates according to trade weights
%                 x_rn = (0.244 * d_in.('RS_EZ'){limit} +  ...
%                     0.100 * d_in.('RS_JP'){limit} +  ...
%                     0.124 * d_in.('RS_US'){limit}) / ...
%                     (0.244 + 0.100 + 0.124);
%                 d_out.(map{find(strcmp(map(:,1),'x_rn')),1}) = x_rn;
%                 
                % weight exchange rates according to trade weights
                x = exp(d_in.('L_S_EZ'){limit} / 100) /  d_out.zarusd{limit};
                y = exp(d_in.('L_S_JP'){limit} / 100) /  d_out.zarusd{limit};
                z = 1                                /  d_out.zarusd{limit};
                
                s = (0.2926 + 0.0603 + 0.1372 + 0.2054)                      / ...
                    (0.2926           * x / mean(x(qq(2010,1):qq(2010,4)))   + ...
                    0.0603            * y / mean(y(qq(2010,1):qq(2010,4)))   + ...
                    (0.1372 + 0.2054) * z / mean(z(qq(2010,1):qq(2010,4)))  );
                s = s / mean(s(qq(2010,1):qq(2010,4))) ;
                d_out.(map{find(strcmp(map(:,1),'s')),1}) = s;
                
                % map (ignoring NAs) and limit all series to the specified range (if specified)
                if exist('limit','var')
                    for i = 1:numel(map)/2
                        if ~strcmp(map{i,2},'NA')
                            d_out.(map{i,1}) =  d_in.(map{i,2}){limit};
                        end
                    end
                else
                    for i = 1:numel(map)/2
                        if ~strcmp(map{i,2},'NA')
                            d_out.(map{i,1}) =  d_in.(map{i,2}){limit};
                        end
                    end
                end
            else
                error('No such database type, options are assumptions, base, dim, or gpm');
            end
        end
    end
end
end