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

varargin = unique(cellfun(@convertNumToChar, varargin, 'UniformOutput', false));
cachedir = mcrcachedir;
arch = computer('arch');
if(strfind(computer('arch'), 'win'))
    batroot = '\\mathworks\devel\bat';
else
    batroot = '/mathworks/devel/bat';
end
agentbatpath = ['derived' filesep 'obj' filesep arch filesep 'installagent_installer'];

agentSearchPath = {[matlabroot,filesep,'toolbox',filesep,'compiler',filesep,'deploy',filesep,arch, filesep, 'InstallAgent.zip'];
    [matlabroot,filesep,agentbatpath, filesep, 'InstallAgent.zip'];
    [batroot,filesep,'Bdeploy_integ',filesep,'perfect',filesep,'matlab',filesep,agentbatpath, filesep, 'InstallAgent.zip'];
    [batroot,filesep,'Binstall',filesep,'perfect',filesep,'matlab',filesep,agentbatpath, filesep, 'InstallAgent.zip']};

mcrinstallerfilelocation = mcrinstallerfile();

index = find(cellfun(@exist, agentSearchPath)==2,1);
if( isempty(index)  )
    error(message('Compiler:buildinstallagent:couldNotFindInstallAgent'));
end
installagentfilelocation = agentSearchPath{index};

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

% We only want to reconstruct the zip file if either the mcrinstaller
% or installagent zip files have been updated since the last build
needsUpdate = true;
mcrinstallerFile = java.io.File(mcrinstallerfilelocation);
timestamp = char(java.util.Date(mcrinstallerFile.lastModified()).toString());
installagentFile = java.io.File(installagentfilelocation);
timestamp = [timestamp char(java.util.Date(installagentFile.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));
    agentuniquepath = fullfile(tempdir, char(java.util.UUID.randomUUID));
    c = onCleanup(@()deleteAllFolders(mcruniquepath,agentuniquepath));
    unzip(mcrinstallerfilelocation, mcruniquepath);
    mkdir(agentuniquepath);
    % Drop the timestamp file here so it gets zipped up
    fid = fopen(fullfile(agentuniquepath,timestampfile),'w');
    if( fid ~= -1 )
        fwrite(fid, timestamp);
        fclose(fid);
    end
    unzip(installagentfilelocation, agentuniquepath);
    fileList = {};
    if( nargin > 0)
        fileList = cellfun(@(n) copyProductFiles(n, mcruniquepath, agentuniquepath), varargin, 'UniformOutput', false);
    end
    if(isempty(fileList)) % if no files were copied then copy everything
        copyfile([mcruniquepath filesep 'archives'], [agentuniquepath filesep 'archives']);
    end
    if(exist(installagentzipfilepath, 'file') == 2)
        delete(installagentzipfilepath);
    end
    zip(installagentzipfilepath, '*', agentuniquepath);
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 productFiles = copyProductFiles(productNumber, mcruniquepath, agentuniquepath)
[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(mcruniquepath, 'archives', lines);
dest = fullfile(agentuniquepath, 'archives', lines);
productFiles = cellfun(@copyfileEx, source, dest, 'UniformOutput', false);
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
