function out = buildinstallagent(varargin)
%   BUILDINSTALLAGENT creates the Install Agent with complete archives
%   extracted from the MCR Installer

mcr_product_ids = unique(cellfun(@convertNumToChar, varargin, 'UniformOutput', false));
cachedir = mcrcachedir;
arch = computer('arch');

mcrinstallerfilelocation = compiler.runtime.installer();
if isempty(mcrinstallerfilelocation)
    error(message('Compiler:buildinstallagent:couldNotFindMCRInstaller'));
end

installagentdir = [strrep(cachedir, 'mcrCache', 'installAgent') filesep arch];
if (~exist(installagentdir, 'dir'))
    [s, m, i] = mkdir(installagentdir);
    if(s ~= 1)
        error(i,m);
    end
end
installagentzipfilepath = [installagentdir filesep getInstallAgentFileName(mcr_product_ids)];
timestampfile = 'timestamp.ts';

% We only want to reconstruct the zip file if the mcrinstaller
% has been updated since the last build
needsUpdate = true;
mcrinstallerFile = java.io.File(mcrinstallerfilelocation);
timestamp = char(java.util.Date(mcrinstallerFile.lastModified()).toString());

if (exist(installagentzipfilepath, 'file'))
    try
        zipfile = java.util.zip.ZipFile(java.io.File(installagentzipfilepath));
        entry = zipfile.getEntry(timestampfile);
        if ~isempty(entry)
            stream = zipfile.getInputStream(entry);
            datalength = stream.available;
            old_timestamp = zeros(1,datalength);
            for i=1:datalength
                old_timestamp(i) = stream.read();
            end
            needsUpdate = ~strcmp(char(old_timestamp),timestamp);
        end
    catch
        % If there are any errors the cache is invalid.
        % continue with rebuilding the install agent.
    end
    if exist('zipfile', 'var') == 1 && isa(zipfile, 'java.util.zip.ZipFile')
        zipfile.close();
    end
end

if (needsUpdate)
    mcruniquepath = fullfile(tempdir, char(java.util.UUID.randomUUID));
    c = onCleanup(@()deleteAllFolders(mcruniquepath));
    unzip(mcrinstallerfilelocation, mcruniquepath);
    % Drop the timestamp file here so it gets zipped up
    fid = fopen(fullfile(mcruniquepath,timestampfile),'w');
    if( fid ~= -1 )
        fwrite(fid, timestamp);
        fclose(fid);
    end
    if( nargin > 0)
        prepareProductFiles(mcr_product_ids, mcruniquepath);
    end
    if(exist(installagentzipfilepath, 'file') == 2)
        delete(installagentzipfilepath);
    end
    zip(installagentzipfilepath, '*', mcruniquepath);
end
if(exist(installagentzipfilepath, 'file') == 2)
    out = installagentzipfilepath;
else
    out = '';
end
% Store the base install agent cache directory in preferences.
pathStr = fileparts(out);
if ~isempty(pathStr)
    pathStr = fileparts(pathStr);
    com.mathworks.services.Prefs.setStringPref('CompilerInstallAgentCache', pathStr);
end
end

function installagent = getInstallAgentFileName(products)
installagent = 'InstallAgent';
for i=1:length(products)
    installagent = [installagent,'_',products{i}]; %#ok
end
installagent = [installagent,'.zip'];
end

function a=convertNumToChar(b)
a='';
if(isnumeric(b) )
    a=num2str(b);
elseif ischar(b)
    a=b;
end
end

function prepareProductFiles(product_ids, mcruniquepath)
% Rename the original "archives" folder to "archives_original"
% Create a new empty folder "archives"
% Copy product files from "archives_original" to "archives"
% Remove "archives_original"

archives_dir = fullfile(mcruniquepath, 'archives');
src_archives_dir = [archives_dir '_original'];
movefile(archives_dir, src_archives_dir);

dst_archives_dir = archives_dir;
[s, m, i] = mkdir(dst_archives_dir);
if(s ~= 1)
    error(i,m);
end

cellfun(@(n)copyProductFiles(n), product_ids, 'UniformOutput', false);

productdata_dir = fullfile(mcruniquepath, 'productdata');
deleteAllFolders(src_archives_dir, productdata_dir);

    function copyProductFiles(productNumber)
    [fileID, ~] = fopen(fullfile(mcruniquepath, 'productdata', [productNumber '.txt']));
    if(fileID == -1)
        error(message('Compiler:buildinstallagent:couldNotFindProductInMCR', productNumber));
    end
    c=onCleanup(@()fclose(fileID));
    lines = textscan(fileID, '%s', 'CommentStyle', '#');
    lines = lines{1, 1};

    source = fullfile(src_archives_dir, lines);
    dest = fullfile(dst_archives_dir, lines);
    cellfun(@copyfileEx, source, dest, 'UniformOutput', false);
    end
end

function fileCopied = copyfileEx(source, dest)
dir = fileparts(dest);
if(exist(dir, 'dir') ~= 7)
    [s, m] = mkdir(dir);
    if(s == 0)
        error(m);
    end
end
[s, m] = copyfile(source, dest);
if(s ~= 1)
    error(m);
end
fileCopied = dest;
end

function deleteAllFolders(varargin)
for i=1:nargin
    if(exist(varargin{i},'dir') )
        rmdir(varargin{i},'s');
    elseif(exist(varargin{i}, 'file') )
        delete(varargin{i});
    end
end
end
