function dec = projectCompleteDec(dec, par)
% project a complete proper representation
%
% Initial data is already present (facet normals, mapping, properData).
% 
% THIS IS NO USER FUNCTION

% The elk-library: convex geometry applied to crystallization modeling.
%   Copyright (C) 2013 Alexander Reinhold
%
% This program is free software: you can redistribute it and/or modify it 
%   under the terms of the GNU General Public License as published by the 
%   Free Software Foundation, either version 3 of the License, or (at your 
%   option) any later version.
%
% This program is distributed in the hope that it will be useful, but 
%   WITHOUT ANY WARRANTY; without even the implied warranty of 
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
%   General Public License for more details.
%
% You should have received a copy of the GNU General Public License along 
%   with this program.  If not, see <http://www.gnu.org/licenses/>.

%% Things, we already know
%! DEV: In principle, the projection might be proper (in case of identity
%    as projection matrix). But this is rarely the case and ignored, here,
%    with no loss of functionality.
dec.isProper = 0;
dec.isComplete = 1;

%% Validity cone
if par.verbose, disp('Project validity cone .. ');end
% This is a simple transformation
validityConeData.A = dec.properData.validityCone.A * ...
    dec.properData.mappingNewToProper;
% remove zero rows and trim
validityConeData.A = trimConstraintMatrix(validityConeData.A, par.zerotol, 1);
% remove duplicate rows
validityConeData.A = unique(validityConeData.A, 'rows');

% add validity cone information, which adds the fields: validityCone, se
%   seScaledToClose, nS, centerRay. The following fiels are final:
%   validityCone, centerRay - all other fields will be extended.
dec = addValidityCone(dec, validityConeData.A, par.zerotol);
%! DEV: what happens when the validity cone is empty??
if par.verbose
    if dec.validityCone.volume == 0
        disp('.. empty validity cone, there will be no valid hC-vectors.');
    else
        disp(['.. validity cone has volume: ' num2str(dec.validityCone.volume)]);
    end
    disp('done.');
end

%% Facet validity data
if par.verbose, disp('Project facet validity data .. ');end
dec = projectFacetValidityData(dec, dec.properData.facetValidityData, ...
                               dec.properData.mappingNewToProper, ...
                               par.zerotol);
if par.verbose, disp('done.');end

%% Correct centerRay
if par.verbose, disp('Construct center ray .. ');end
% the valditity cone might be empty, resulting in an empty center ray. To
%   compensate this, we construct a meaningful closure from the
%   nonempty-polytope cone.
nonemptyCone = obtainFacetValidityCone(dec, dec.nH + 1);
dec.centerRay = mean(computeExtremeRaysFromCone(nonemptyCone.A, ...
    par.zerotol), 1)';
% correct SEs that are scaled to close
% dec.seScaledToClose = scaleToClose(dec.seScaledToClose, dec);
if par.verbose, disp('done.');end

%% Confinement cone
if par.verbose, disp('Decompose non-empty polytope cone .. ');end
% I need the scaledToClose extreme rays of the non-empty polytope cone
nonemptyCone = obtainFacetValidityCone(dec, dec.nH + 1);
% rayMatrix = computeExtremeRaysFromCone(nonemptyCone.A, zerotol);

% then, find all confined partitions
partitionData = decomposeCone(dec, nonemptyCone.A, ...
    @generateConfinementPartition, par.zerotol, par.verbose);
if par.verbose, disp('done.');end

if par.verbose, disp('Add confinement partitions and structuring elements.. ');end
dec = addConfinementPartitionData(dec, partitionData, par.zerotol);
dec = addConfinementMappingData(dec);
if par.verbose, disp('done.');end

%% Validity (orthogonal) mapping
if par.verbose, disp('Add validity mapping data.. ');end
% if dec.validityCone.volume == 0
%     % the validity cone is empty, every mapping goes to zero
%     dec.validityMappingData.A = zeros(0, dec.nC);
%     dec.validityMappingData.responsibleMatrix = zeros(0, 3);
%     dec.validityMappingData.projectionList = zeros(dec.nC);
%     dec.validityMappingData.targetDimensionVector = 0;
% else
    dec.validityMappingData = generateOrthogonalProjectionDataForCone(...
        dec.validityCone.A, ...
        dec.seScaledToClose(dec.validityCone.seIndexVector, :), ...
        par.zerotol);
% end
if par.verbose, disp('done.');end