function [X,FLAG] = specget(THIS,QUERY)
% SPECGET  [Not a public function] Implement GET method for model objects.
%
% Backend IRIS function.
% No help provided.

% -IRIS Toolbox.
% -Copyright (c) 2007-2012 Jaromir Benes.

%**************************************************************************

[X,FLAG] = specget@metaobj(THIS,QUERY);
if FLAG
    return
end

X = [];
FLAG = true;

QUERY = model.myalias(QUERY);

sslevel = [];
ssgrowth = [];
dtlevel = [];
dtgrowth = [];
level = [];
growth = [];
sstateList = { ...
    'ss','sslevel','level','ssgrowth','growth', ...
    'dt','dtlevel','dtgrowth', ...
    'ss+dt','sslevel+dtlevel','ssgrowth+dtgrowth', ...
    };

% Query relates to steady state.
if any(strcmpi(QUERY,sstateList))
    [sslevel,ssgrowth,dtlevel,dtgrowth,level,growth] = xxsstate(THIS);
    ssname = THIS.name(THIS.nametype <= 3);
end

nx = length(THIS.solutionid{2});
nb = size(THIS.solution{1},2);
nf = nx - nb;
nalt = size(THIS.Assign,3);

realsmall = getrealsmall();

cell2structfunc = @(x,list) cell2struct( ...
    num2cell(permute(x,[2,3,1]),2), ...
    list(:),1);

% Check availability of solution.
chksolution = false;
addparams = false;

switch QUERY
    
    case 'ss'
        X = cell2structfunc(sslevel+1i*ssgrowth,ssname);
        addparams = true;
        
    case 'sslevel'
        X = cell2structfunc(sslevel,ssname);
        addparams = true;
        
    case 'ssgrowth'
        X = cell2structfunc(ssgrowth,ssname);
        addparams = true;
        
    case 'dt'
        X = cell2structfunc(dtlevel+1i*dtgrowth,ssname);
        addparams = true;
        
    case 'dtlevel'
        X = cell2structfunc(dtlevel,ssname);
        addparams = true;
        
    case 'dtgrowth'
        index = THIS.nametype == 1;
        X = cell2structfunc(dtgrowth,ssname);
        addparams = true;
        
    case 'ss+dt'
        X = cell2structfunc(level+1i*growth,ssname);
        addparams = true;
        
    case 'sslevel+dtlevel'
        X = cell2structfunc(level,ssname);
        addparams = true;
        
    case 'ssgrowth+dtgrowth'
        X = cell2structfunc(growth,ssname);
        addparams = true;
        
    case {'eig','eigval','roots'}
        X = eig(THIS);
        
    case 'rlist'
        X = {THIS.outside.lhs{:}};
        
    case {'yeqtn','xeqtn'}
        index = find(QUERY(1) == 'yx');
        X = THIS.eqtn(THIS.eqtntype == index);
        
    case {'deqtn'}
        X = THIS.eqtn(THIS.eqtntype == 3);
        X(cellfun(@isempty,X)) = [];
        
    case {'leqtn'}
        X = THIS.eqtn(THIS.eqtntype == 4);
        
    case 'reqtn'
        n = length(THIS.outside.rhs);
        X = cell([1,n]);
        for i = 1 : n
            X{i} = sprintf('%s=%s;', ...
                THIS.outside.lhs{i},THIS.outside.rhs{i});
        end
        % Remove references to database d from reporting equations.
        X = regexprep(X,'d\.([a-zA-Z])','$1');
        
    case {'nonlineqtn'}
        X = THIS.eqtn(THIS.nonlin);
        
    case {'nonlinlabel'}
        X = THIS.eqtnlabel(THIS.nonlin);
        
    case 'rlabel'
        X = THIS.outside.label;
        
    case 'yvector'
        X = THIS.solutionvector{1};
        
    case 'xvector'
        X = THIS.solutionvector{2};
        
    case 'xfvector'
        X = THIS.solutionvector{2}(1:nf);
        
    case 'xbvector'
        X = THIS.solutionvector{2}(nf+1:end);
        
    case 'evector'
        X = THIS.solutionvector{3};
        
    case {'ylog','xlog','elog'}
        index = find(QUERY(1) == 'yxe');
        X = THIS.log(THIS.nametype == index);
        
    case 'yid'
        X = THIS.solutionid{1};
        
    case 'xid'
        X = THIS.solutionid{2};
        
    case 'eid'
        X = THIS.solutionid{3};
        
    case {'eylist','exlist'}
        t = THIS.tzero;
        nname = length(THIS.name);
        index = nname*(t-1) + find(THIS.nametype == 3);
        eyoccur = THIS.occur(THIS.eqtntype == 1,index);
        exoccur = THIS.occur(THIS.eqtntype == 2,index);
        eyindex = any(eyoccur,1);
        exindex = any(exoccur,1);        
        elist = THIS.name(THIS.nametype == 3);
        if QUERY(2) == 'y'
            X = elist(eyindex);
        else
            X = elist(exindex);
        end
        
    case 'eqtn'
        X = cell(1,4);
        for i = [1,2,4]
            X{i} = THIS.eqtn(THIS.eqtntype == i);
        end
        nonemptyeqtn = ~cellfun(@isempty,THIS.eqtn);
        X{3} = THIS.eqtn(THIS.eqtntype == 3 & nonemptyeqtn);
        
    case {'derivatives','xderivatives','yderivatives'}
        doderivatives();
        
    case {'wrt','xwrt','ywrt'}
        dowrt();
        
    case 'label'
        X = cell(1,4);
        for i = [1,2,4]
            X{i} = THIS.eqtnlabel(THIS.eqtntype == i);
        end
        nonemptyeqtn = ~cellfun(@isempty,THIS.eqtn);
        X{3} = THIS.eqtnlabel(THIS.eqtntype == 3 & nonemptyeqtn);
        
    case {'xlabel','ylabel','dlabel','llabel'}
        index = find(QUERY(1) == 'yxdl');
        if any(index == [1,2,4])
            X = THIS.eqtnlabel(THIS.eqtntype == index);
        else
            nonemptyeqtn = ~cellfun(@isempty,THIS.eqtn);
            X = THIS.eqtnlabel(THIS.eqtntype == index & nonemptyeqtn);
        end
        
    case 'link'
        X = cell2struct(THIS.eqtn(THIS.eqtntype == 4), ...
            THIS.name(THIS.Refresh),2);
        
    case {'diffuse','nonstationary','stationary', ...
            'stationarylist','nonstationarylist'}
        dostationary();
        
    case 'maxlag'
        X = min(imag(THIS.systemid{2}));
        
    case 'maxlead'
        X = max(imag(THIS.systemid{2})) + 1;
        
    case {'icond','initcond','required'}
        key = THIS.solutionid{2}(nf+1:end);
        X = cell([1,nalt]);
        for ialt = 1 : nalt
            X{ialt} = myvector(THIS,key(THIS.icondix(1,:,ialt))-1i);
        end
        if nalt == 1
            X = X{1};
        end
        
    case {'forward'}
        ne = sum(THIS.nametype == 3);
        X = size(THIS.solution{2},2)/ne - 1;
        chksolution = true;
        
    case {'stableroots','unitroots','unstableroots'}
        switch QUERY
            case 'stableroots'
                index = abs(THIS.eigval) < (1 - realsmall);
            case 'unstableroots'
                index = abs(THIS.eigval) > (1 + realsmall);
            case 'unitroots'
                index = abs(abs(THIS.eigval) - 1) <= realsmall;
        end
        X = nan(size(THIS.eigval));
        for ialt = 1 : nalt
            n = sum(index(1,:,ialt));
            X(1,1:n,ialt) = THIS.eigval(1,index(1,:,ialt),ialt);
        end
        X(:,all(isnan(X),3),:) = [];
        
    case 'epsilon'
        X = THIS.epsilon;
        
    case {'torigin','baseyear'}
        X = THIS.torigin;
        
    case 'userdata'
        X = userdata(THIS);
        
    case {'activeshocks','inactiveshocks'}
        X = cell([1,nalt]);
        for ialt = 1 : nalt
            list = THIS.name(THIS.nametype == 3);
            stdvec = THIS.Assign(1, ...
                end-sum(THIS.nametype == 3)+1:end,ialt);
            if QUERY(1) == 'a'
                list(stdvec == 0) = [];
            else
                list(stdvec ~= 0) = [];
            end
            X{ialt} = list;
        end
        
    case 'nx'
        X = length(THIS.solutionid{2});
    case 'nb'
        X = size(THIS.solution{7},1);
    case 'nf'
        X = length(THIS.solutionid{2}) - size(THIS.solution{7},1);
    case 'ny'
        X = length(THIS.solutionid{1});
    case 'ne'
        X = length(THIS.solutionid{3});
        
    case 'build'
        X = THIS.build;
        
    otherwise
        FLAG = false;
        
end

if chksolution
    % Report solution(s) not available.
    [solutionflag,index] = isnan(THIS,'solution');
    if solutionflag
        utils.warning('model', ...
            '#Solution_not_available', ...
            sprintf(' #%g',find(index)));
    end
end

% Add parameters, std devs and non-zero cross-corrs.
if addparams
    % Use a for loop to make sure the newly added parameters appear last in the
    % database.
    p = specget(THIS,'parameters');
    list = fieldnames(p);
    for j = 1 : length(list)
        X.(list{j}) = p.(list{j});
    end
end

% Nested functions.

%**************************************************************************
    function dostationary()
        chksolution = true;
        realsmall = getrealsmall();
        id = [THIS.solutionid{1:2}];
        t0 = imag(id) == 0;
        name = THIS.name(real(id(t0)));
        [~,index] = isnan(THIS,'solution');
        status = nan([sum(t0),nalt]);
        for iialt = find(~index)
            unit = abs(abs(THIS.eigval(1,1:nb,iialt)) - 1) <= realsmall;
            dy = any(abs(THIS.solution{4}(:,unit,iialt)) > realsmall,2).';
            df = any(abs(THIS.solution{1}(1:nf,unit,iialt)) > realsmall,2).';
            db = any(abs(THIS.solution{7}(:,unit,iialt)) > realsmall,2).';
            d = [dy,df,db];
            if strncmp(QUERY,'s',1)
                % Stationary.
                status(:,iialt) = transpose(double(~d(t0)));
            else
                % Non-stationary.
                status(:,iialt) = transpose(double(d(t0)));
            end
        end
        try %#ok<TRYNC>
            status = logical(status);
        end
        if ~isempty(strfind(QUERY,'list'))
            % List.
            if nalt == 1
                X = name(status == true | status == 1);
                X = X(:)';
            else
                X = cell([1,nalt]);
                for ii = 1 : nalt
                    X{ii} = name(status(:,ii) == true | status(:,ii) == 1);
                    X{ii} = X{ii}(:)';
                end
            end
        else
            % Database.
            X = cell2struct(num2cell(status,2),name(:),1);
        end
    end
% dostationary().

%**************************************************************************
    function doderivatives()
        if strncmpi(QUERY,'y',1)
            select = THIS.eqtntype == 1;
        elseif strncmpi(QUERY,'x',1)
            select = THIS.eqtntype == 2;
        else
            select = THIS.eqtntype <= 2;
        end
        neqtn = sum(select);
        X = cell(1,neqtn);
        for iieq = find(select)
            u = char(THIS.deqtnF{iieq});
            u = regexprep(u,'^@\(.*?\)','','once');
            %u = sydney.myeqtn2symb(u);
            %u = sydney(u);
            %u = char(u,'human');
            %u = sydney.mysymb2eqtn(u);
            replaceplusminus = @doreplaceplusminus; %#ok<NASGU>
            replacezero = @doreplacezero; %#ok<NASGU>
            u = regexprep(u,'\<x\>\(:,(\d+),t([+\-]\d+)\)', ...
                '${replaceplusminus($1,$2)}');
            u = regexprep(u,'\<x\>\(:,(\d+),t\)', ...
                '${replacezero($1)}');
            X{iieq} = u;
        end
        
        function c = doreplaceplusminus(c1,c2)
            index = sscanf(c1,'%g');
            c = [THIS.name{index},'{',c2,'}'];
        end
        
        function c = doreplacezero(c1)
            index = sscanf(c1,'%g');
            c = THIS.name{index};
        end
        
    end
% doderivatives().
   
%**************************************************************************
    function dowrt()
        if strncmpi(QUERY,'y',1)
            select = THIS.eqtntype == 1;
        elseif strncmpi(QUERY,'x',1)
            select = THIS.eqtntype == 2;
        else
            select = THIS.eqtntype <= 2;
        end        
        neqtn = sum(select);
        X = cell(1,neqtn);
        for iieq = find(select)
            [tmocc,nmocc] = myfindoccur(THIS,iieq,'variables_shocks');
            tmocc = tmocc - THIS.tzero;
            nocc = length(tmocc);
            X{iieq} = cell(1,nocc);
            for iiocc = 1 : nocc
                c = THIS.name{nmocc(iiocc)};
                if tmocc(iiocc) ~= 0
                    c = sprintf('%s{%+g}',c,tmocc(iiocc));
                end
                if THIS.log(nmocc(iiocc))
                    c = ['log(',c,')']; %#ok<AGROW>
                end
                X{iieq}{iiocc} = c;
            end
        end
    end
% dowrt().

end

% Subfunctions.

%**************************************************************************
function [sslevel,ssgrowth,dtlevel,dtgrowth,ssdtlevel,ssdtgrowth] ...
    = xxsstate(THIS)

Assign = THIS.Assign(1,THIS.nametype <= 3,:);
islog = THIS.log(1,THIS.nametype <= 3);
n = sum(THIS.nametype <= 3);
ny = sum(THIS.nametype == 1);
nalt = size(Assign,3);

% Steady states.
sslevel = real(Assign);
ssgrowth = imag(Assign);

% Fix missing (=zero) growth in steady states of log variables.
ssgrowth(ssgrowth == 0 & islog(1,:,ones(1,nalt))) = 1;

% Retrieve dtrends.
[const,ttrend] = mydtrendsrequest(THIS,'sstate');
const = permute(const,[3,1,2]);
ttrend = permute(ttrend,[3,1,2]);
const(:,ny+1:n,:) = 0;
ttrend(:,ny+1:n,:) = 0;
dtlevel = nan(1,n,nalt);
dtlevel(1,~islog,:) = const(1,~islog,:);
dtlevel(1,islog,:) = exp(const(1,islog,:));
dtgrowth = nan(1,n,nalt);
dtgrowth(1,~islog,:) = ttrend(1,~islog,:);
dtgrowth(1,islog,:) = exp(ttrend(1,islog,:));

% Steady state plus dtrends.
ssdtlevel = sslevel;
ssdtlevel(1,islog,:) = ssdtlevel(1,islog,:) .* dtlevel(1,islog,:);
ssdtlevel(1,~islog,:) = ssdtlevel(1,~islog,:) + dtlevel(1,~islog,:);
ssdtgrowth = ssgrowth;
ssdtgrowth(1,islog,:) = ssdtgrowth(1,islog,:) .* dtgrowth(1,islog,:);
ssdtgrowth(1,~islog,:) = ssdtgrowth(1,~islog,:) + dtgrowth(1,~islog,:);

end
% xxsstate().