classdef ValidateCCS < matlab.hwmgr.internal.hwsetup.ValidateLocation
    % ValidateCCS - Screen implementation to enable users to select the
    % CCS Tool chain.

    %   Copyright 2017-2023 The MathWorks, Inc.

    properties
        DSSInstallDir
        isValidated = true;
        ValidateButton
        StatusTable
        StatusTableTitle
        SavedSelectedProcessors
        screenReady = false;
    end

    properties(Access = private)
        BusySpinner
    end

    methods
        function obj = ValidateCCS(varargin)
            % call to the base class constructor
            obj@matlab.hwmgr.internal.hwsetup.ValidateLocation(varargin{:});
            obj.ValidateButton = matlab.hwmgr.internal.hwsetup.Button.getInstance(obj.ContentPanel);

            %CCS Validation will bring in these widgets
            obj.StatusTable = matlab.hwmgr.internal.hwsetup.StatusTable.getInstance(obj.ContentPanel);
            obj.StatusTableTitle = matlab.hwmgr.internal.hwsetup.Label.getInstance(obj.ContentPanel);

            % Title for Status Tables
            obj.StatusTableTitle.Position = [20 205 450 60];
            obj.StatusTableTitle.Color = matlab.hwmgr.internal.hwsetup.util.Color.WHITE;

            %Titles
            obj.StatusTableTitle.Text = message('TIC2000:hwsetup:StatusTableTitle').getString;

            % Add selected processor details here
            %                 processorlist = obj.Workflow.SelectedProcessors;
            obj.StatusTable.Status = {''};
            obj.StatusTable.Steps = {''};

            % hide all these widgets
            obj.StatusTable.Visible = 'off';
            obj.StatusTableTitle.Visible = 'off';

            % Set the Title Text
            obj.Title.Text = message('TIC2000:hwsetup:ValidateCCSTitle').getString;

            % Set the Description text
            obj.Description.Text = ...
                message('TIC2000:hwsetup:ValidateCCSDescription').getString;


            % Help Text
            obj.HelpText.WhatToConsider = message('TIC2000:hwsetup:SpecifyValidFolderWithCCSDefaults').getString;

            % Update Installed locations of CCS and CGT
            % Add the path from the stored Workflow variable

            if isempty(obj.Workflow.CCSInstallLocation)
                [obj.Workflow.CCSInstallLocation, obj.Workflow.CCSInstallVersion] = obj.Workflow.HardwareInterface.getCCSInfo();
            end

            % Hardcode some default value
            if isempty(obj.Workflow.CCSInstallLocation)
                obj.ValidateEditText.Text = obj.Workflow.HardwareInterface.dummyCCSPath;
                % Disable Next, to make validation mandatory
                obj.NextButton.Enable = 'off';
            else
                obj.ValidateEditText.Text = char(obj.Workflow.CCSInstallLocation);
            end

            obj.ValidateEditText.ValueChangedFcn = @obj.FolderValidation;

            % Disable Next, to make validation mandatory
            obj.NextButton.Enable = 'off';

            % Validate button properties
            obj.ValidateButton.Text = message('TIC2000:hwsetup:Validate').getString;
            obj.ValidateButton.ButtonPushedFcn = @obj.validatecbk;
            obj.ValidateButton.Position = [20 270 143 22];
            obj.ValidateButton.Color = matlab.hwmgr.internal.hwsetup.util.Color.MWBLUE;
            obj.ValidateButton.FontColor = matlab.hwmgr.internal.hwsetup.util.Color.WHITE;


            % browse button callback
            obj.BrowseButton.ButtonPushedFcn = @obj.custombrowseDirectory;
            obj.BrowseButton.Color = matlab.hwmgr.internal.hwsetup.util.Color.MWBLUE;
            obj.BrowseButton.FontColor = matlab.hwmgr.internal.hwsetup.util.Color.WHITE;

            %SaveSelectedProcessors
            obj.SavedSelectedProcessors = obj.Workflow.SelectedProcessors;
            % Do not place any code below this line in this function
            obj.screenReady = true;
        end

        function custombrowseDirectory(obj, ~, ~)
            dir = uigetdir(obj.ValidateEditText.Text, message('TIC2000:hwsetup:CCSBrowseHelp').getString);
            obj.Workflow.Window.bringToFront();
            if dir % If the user cancel's the file browser, uigetdir returns 0.
                % When a new location is selected, then set that location value
                % back to show it in edit text area. (ValidateEditText.Text).
                obj.ValidateEditText.Text = dir;
            end
        end

        function FolderValidation(obj, ~, ~)
            % Disable Next, to make validation mandatory
            obj.NextButton.Enable = 'off';
        end

        function out = getNextScreenID(obj)
            if ~isobject(obj) || isempty(obj.screenReady) || ~(obj.screenReady)
                % Placeholder if user clicks next quickly before the screen is
                % populated with options stay in the same screen
                out = [];
            else
                ProcessorC2000WareMapObj = obj.Workflow.ProcessorC2000WareMapObj;
                selectedprocessors = obj.Workflow.SelectedProcessors;
                wareNeededIdx = 0;
                for i=1:numel(selectedprocessors)
                    if any(ismember(ProcessorC2000WareMapObj.keys, selectedprocessors{i}))
                        wareNeededIdx = wareNeededIdx + 1;
                    end
                end
                if (wareNeededIdx > 0)
                    if isempty(obj.Workflow.C2000WareLocation)
                        % Check registry to pick installed C2000Ware during setup
                        obj.disableScreen();
                        obj.BusySpinner = matlab.hwmgr.internal.hwsetup.BusyOverlay.getInstance(obj.ContentPanel);
                        obj.BusySpinner.Text = message('TIC2000:hwsetup:AutoFind3P').getString;
                        [obj.Workflow.C2000WareLocation, obj.Workflow.C2000WareVersion] = obj.Workflow.HardwareInterface.getC2000WareInfo();
                        obj.enableScreen;
                    end

                    out = 'codertarget.tic2000.hwsetup.ValidateC2000Ware';
                else
                    if strcmp(obj.Workflow.BaseCode, 'TIC2000_BLOCKSET')
                        out = 'codertarget.tic2000.hwsetup.ValidateCGT';
                    else
                        out = 'codertarget.tic2000.hwsetup.ConfirmTPInstallation';
                    end
                end
                % Disable next button to prevent multiple press
                obj.NextButton.Enable = 'off';
            end
        end

        function reinit(obj)
            % hide the ignore checkbox if possible or uncheck selection
            % Disable Next, to make validation mandatory
            % Since validation is mandatory, remove previous status message
            % and update help text to original

            obj.NextButton.Enable = 'off';
            if ~isempty(obj.BusySpinner) && strcmpi(obj.BusySpinner.Visible, 'on')
                obj.BusySpinner.Visible = 'off';
            end
            obj.HelpText.WhatToConsider = message('TIC2000:hwsetup:SpecifyValidFolderWithCCSDefaults').getString;
            obj.HelpText.AboutSelection = '';

            obj.StatusTable.Visible = 'off';
            obj.StatusTableTitle.Visible = 'off';
        end

        function out = getPreviousScreenID(obj)
            if any(contains(obj.Workflow.SelectedProcessors, 'TI F281x'))
                out = 'codertarget.tic2000.hwsetup.ValidateF281x';
            elseif any(contains(obj.Workflow.SelectedProcessors, 'TI F280x'))
                out = 'codertarget.tic2000.hwsetup.ValidateF280x';
            elseif any(contains(obj.Workflow.SelectedProcessors, 'TI F28044'))
                out = 'codertarget.tic2000.hwsetup.ValidateF28044';
            elseif obj.Workflow.isNeededValidateSUITE
                out = 'codertarget.tic2000.hwsetup.ValidateControlSUITE';
            else
                if strcmp(obj.Workflow.BaseCode, 'TIC2000_BLOCKSET')
                    out = 'codertarget.tic2000.hwsetup.InstallTpSoftware2';
                else
                    if (obj.Workflow.required3PToolCount ==2) && ...
                            obj.Workflow.autoInstall3PTool(2).validationScreenRequired
                        out = 'codertarget.tic2000.hwsetup.ValidateARMCGT';
                    elseif obj.Workflow.autoInstall3PTool(1).validationScreenRequired
                        out = 'codertarget.tic2000.hwsetup.ValidateCGT';
                    else
                        out = 'codertarget.tic2000.hwsetup.InstallTpSoftware2';
                    end
                end
            end
        end

        function validatecbk(obj, ~, ~)
            obj.HelpText.AboutSelection = '';
            obj.HelpText.WhatToConsider = message('TIC2000:hwsetup:SpecifyValidFolderWithCCSDefaults').getString;

            % Validate the path once
            installDir = obj.ValidateEditText.Text;
            % Disable Next, to make validation mandatory
            obj.NextButton.Enable = 'off';

            % callback on Next to validate CCS path
            % reset values
            obj.isValidated = true;
            obj.StatusTable.Visible = 'off';
            obj.StatusTableTitle.Visible = 'off';
            obj.StatusTable.Status = {''};
            obj.StatusTable.Steps = {''};

            if isobject(obj.StatusTable)
                obj.StatusTable.Visible = 'off';
            end

            % scriptingVerFile = 'dss.bat'; this will be used later if
            % needed
            scriptingFolder = fullfile('ccs_base', 'scripting');
            if contains(installDir, 'ccsv4')
                scriptingFolder = fullfile('scripting');
            end
            % Check if debug server scripting is where it is expected
            obj.DSSInstallDir = fullfile(installDir, scriptingFolder);
            obj.Workflow.DSSInstallDir = obj.DSSInstallDir;
            pathNotFound = 0;

            if exist(installDir, 'dir') ~= 7
                obj.HelpText.WhatToConsider = message('TIC2000:hwsetup:HelpTextPathFailure').getString;
                obj.HelpText.AboutSelection = message('TIC2000:hwsetup:ValidateCCSAboutSelection').getString;
                h = warndlg(getString(message('TIC2000:hwsetup:CCSDirectoryDoesNotExist', ...
                    installDir, message('TIC2000:hwsetup:ValidateCCSFolder').getString))); %#ok<NASGU>
                obj.isValidated =  false;
                % Show only Status Title
                obj.StatusTable.Visible = 'off';
                obj.StatusTableTitle.Visible = 'on';
                obj.StatusTableTitle.Text = message('TIC2000:hwsetup:CCSPathNotFound').getString;
                pathNotFound = 1;
            elseif exist(obj.DSSInstallDir, 'dir') ~= 7
                obj.HelpText.WhatToConsider = message('TIC2000:hwsetup:HelpTextPathFailure').getString;
                obj.HelpText.AboutSelection = message('TIC2000:hwsetup:ValidateCCSAboutSelection').getString;
                % Warn user to provide CCS installation parent folder
                h = warndlg(getString(message('TIC2000:hwsetup:CCSParentDirectoryNA', ...
                    installDir, message('TIC2000:hwsetup:ValidateCCSFolder').getString))); %#ok<NASGU>
                obj.isValidated =  false;
                pathNotFound = 1;
            end
            % store new installDir
            obj.Workflow.CCSInstallLocation = installDir;

            % Update CCS version, based on the mentioned CCS
            doclocation = fullfile(installDir, 'doc');

            if contains(installDir, 'ccsv4', 'IgnoreCase', true)
                verFile = fullfile(doclocation, 'ReleaseNote.htm');
                verPattern  = 'Code\s\Composer\sStudio\W*v(\d+(\.\d+)+)';%read the main version X of vX.Y.Z
                ccsVersion = {linkfoundation.util.getVersion(verFile, verPattern)};
                if ~isempty(ccsVersion)
                    obj.Workflow.CCSInstallVersion = ccsVersion{end};
                else
                    obj.Workflow.CCSInstallVersion = '';
                end
            else
                structdir = dir(fullfile(doclocation, '*.htm'));
                if ~isempty(structdir)
                    try
                        verFilesName = {structdir.name}';%Filter the .htm files to be read in directory with key words Release
                        %Note
                        verFileMatch = '\w*Release\w*Note\w*';
                        %Function handle to handle all the htm files at once
                        verFileFunHandle = @(str) cellfun(@(c) ~isempty(c), regexp(verFilesName, str, 'once'));
                        verFile = verFilesName(verFileFunHandle(verFileMatch));
                        %Only one or atleast one release not file should be present
                        if numel(verFile) == 1
                            fid = fopen(fullfile(doclocation, verFile{1}));
                            versionContent = fread(fid, 32768, '*char').'; % Read up to 32Kb chars
                            fclose(fid);
                            % read all possibilities of vX.Y.Z into verInfo
                            verPattern  = 'Code\s\Composer\sStudio\W*v(\d+(\.\d+)+)';
                            verInfo = regexp(versionContent, verPattern, 'tokens');
                            verPattern  = 'CCSv(\d+(\.\d+)+)';
                            verInfo = [verInfo regexp(versionContent, verPattern, 'tokens')];
                            % Convert X.Y.Z to XYZ and find out the maximum
                            % value among them to identify the latest
                            % version number.
                            [~,maxidx] = max(cellfun(@(c) (str2double(strrep(c,'.',''))), verInfo));
                            % Out of multiple versions read from the release note file, consider
                            % the maximum version as valid one.
                            ccsVersion = char(verInfo{maxidx});
                            obj.Workflow.CCSInstallVersion = ccsVersion;
                        else
                            if ~isempty(installDir) % Check the arguments for regexp is non-empty
                                verPattern  = '\d+'; % read the main version X of vX.Y.Z
                                ccsVersion = regexp(installDir, verPattern, 'match');
                                if ~isempty(ccsVersion)
                                    obj.Workflow.CCSInstallVersion = ccsVersion{end};
                                else
                                    obj.Workflow.CCSInstallVersion = '';
                                end
                            else
                                obj.Workflow.CCSInstallVersion = '';
                            end
                        end
                    catch
                        obj.Workflow.CCSInstallVersion = '';
                        obj.HelpText.AboutSelection = message('TIC2000:hwsetup:VersionFailed').getString;
                    end
                else
                    if ~isempty(installDir) % Check the arguments for regexp is non-empty
                        verPattern  = '\d+'; % read the main version X of vX.Y.Z
                        ccsVersion = regexp(installDir, verPattern, 'match');
                        if ~isempty(ccsVersion)
                            obj.Workflow.CCSInstallVersion = ccsVersion{end};
                        else
                            obj.Workflow.CCSInstallVersion = '';
                        end
                    else
                        obj.Workflow.CCSInstallVersion = '';
                    end
                end
            end
            % Extract only first digit from version
            versionMajor = 0;
            if ~isempty(obj.Workflow.CCSInstallVersion)
                versionNumber = str2double(regexp(obj.Workflow.CCSInstallVersion, '(\d+)(\.|$)', 'match'));
                switch numel(versionNumber)
                    case 0
                        versionMajor = 0; %if regexp fails, if version number is weird
                    case 1
                        % If version number is read from html, the value
                        % will be of the format x.y.z and x will be small
                        % number less than 100 (ex. 8, 9, 10, etc.) but if
                        % it is read from folder path then it could be a
                        % number like 1030, 930, 1010, 901 or number in 10s
                        % like 82, 84 or small number like 8, 7, 6. So
                        % multiple by 100 only if it is a small number,
                        % multiply by 10 if it is in 10s to scale it up
                        % with the number to be compared. Lower limit of 30
                        % is kept ot handle the CCS versions upto 3.x which
                        % will be startting from 30 in 10s.

                        % This issue may not be seen in CCS version
                        % calculation during registry read in
                        % WindowshardwareModule.m file
                        
                        if (versionNumber(1) >= 30) && (versionNumber(1) < 100)
                            versionMajor = versionNumber(1) * 10;
                        elseif (versionNumber(1) < 30)
                            versionMajor = versionNumber(1) * 100;
                        end
                    case 2
                        versionMajor = versionNumber(1)*100 + versionNumber(2)*10;
                    case 3
                        versionMajor = versionNumber(1)*100 + versionNumber(2)*10 + versionNumber(3);
                    otherwise
                        versionMajor = versionNumber(1)*100 + versionNumber(2)*10 + versionNumber(3);
                end
            end

            %Validate if Selected Processors ccxml file is present in
            %selected CCS version
            notfound = {''};
            processorlist = obj.Workflow.SelectedProcessors;
            ccspath = obj.ValidateEditText.Text;
            CCSProcessorCCXMLMapObj = obj.Workflow.CCSProcessorCCXMLMapObj;
            id = 1;

            for i=1:numel(processorlist)
                versionfile_evaluate = fullfile(ccspath, 'ccs_base', 'common', 'targetdb', 'devices', CCSProcessorCCXMLMapObj(processorlist{i}));
                if contains(installDir, 'ccsv4', 'IgnoreCase', true)
                    versionfile_evaluate = fullfile(ccspath, 'common', 'targetdb', 'Devices', CCSProcessorCCXMLMapObj(processorlist{i}));
                end
                if ~(2 == exist(versionfile_evaluate, 'file')) || pathNotFound
                    notfound{id} = processorlist{i};
                    obj.isValidated =  false;
                    id = id + 1;
                end
            end

            if obj.isValidated ==  false
                % Status table properties
                obj.StatusTable.ColumnWidth = [20 160];
                obj.StatusTable.Position= [20 20 390 170];

                % Show all these widgets
                obj.StatusTable.Visible = 'on';
                obj.StatusTableTitle.Visible = 'on';


                obj.StatusTable.Steps = notfound;
                obj.StatusTable.Status = {''};
                obj.StatusTable.Status(1:numel(obj.StatusTable.Steps)) = {matlab.hwmgr.internal.hwsetup.StatusIcon.Fail};

                % fit the table based on the size
                w = obj.StatusTable.getWidth();
                h = obj.StatusTable.getHeight();
                init_pos = obj.StatusTable.Position;
                obj.StatusTable.Position  = [init_pos(1) init_pos(2)+init_pos(4)-h w h];

            else
                % Show only one table
                obj.StatusTable.ColumnWidth = [20 410];
                obj.StatusTable.Visible = 'on';
                % Ensure tested CCS version and warn user accordingly
                if (versionMajor ~= str2double(strrep(message('TIC2000:hwsetup:CCSVersion').getString, '.', '')))
                    obj.StatusTable.Steps = {message('TIC2000:hwsetup:InstallTestedCCSVersion', message('TIC2000:hwsetup:CCSVersion').getString).getString};
                    obj.StatusTable.Status(1:numel(obj.StatusTable.Steps)) = {matlab.hwmgr.internal.hwsetup.StatusIcon.Fail};
                    obj.StatusTable.Position = [20 70 410 170];
                else
                    obj.StatusTable.Steps = {message('TIC2000:hwsetup:ValidateCCSSuccessful').getString};
                    obj.StatusTable.Status(1:numel(obj.StatusTable.Steps)) = {matlab.hwmgr.internal.hwsetup.StatusIcon.Pass};
                    obj.StatusTable.Position = [20 210 390 30];
                end
            end
            % Enable Next button
            obj.NextButton.Enable = 'on';
        end
    end
end