function utidplot(sys, data, signaltype)
%UTIDPLOT  Utility code used for plotting data.

%   Copyright 2005-2023 The MathWorks, Inc.

if isempty(data)
   disp('Empty data set.')
   return;
end

% Determine if the signal is from simulation or prediction
switch lower(signaltype)
   case 'simulated'
      isSimulation = true();
   case 'predicted'
      isSimulation = true();
   otherwise
      assert(false());
end

% Determine figure name
figname = sys.Name;
if ~isempty(figname)
   figname = [figname ': ' sys.Report.Status];
else
   figname = sys.Report.Status;
end

FRDFlag = isa(data,'frd');
if FRDFlag
   data = iddata(idfrd(data),'me');
elseif ~isa(data, 'iddata')
   Warn2 = ctrlMsgUtils.SuspendWarnings('Ident:iddata:MoreOutputsThanSamples');
   data = iddata(data, []);
   delete(Warn2)
end

% Determine if this is a time- or frequency-domain plot
switch lower(pvget(data, 'Domain'))
   case 'time'
      isTimeDomainPlot = true();
   case 'frequency'
      isTimeDomainPlot = false();
   otherwise
      assert(false());
end

% Retrieve variables from data and sys
ne = size(data, 'Ne');
nu = size(data,'Nu');
prederr = pvget(data, 'OutputData');
predinp = pvget(data, 'InputData');
SamplingInstants = pvget(data, 'SamplingInstants');
ExperimentName = pvget(data, 'ExperimentName');
ny = size(sys, 1);
OutputName = sys.OutputName;
OutputUnit = sys.OutputUnit;
TimeUnit = sys.TimeUnit;
if isTimeDomainPlot
   FrequencyUnit = '';
else
   FrequencyUnit = data.FrequencyUnit;
   if endsWith(FrequencyUnit,'/TimeUnit')
      FrequencyUnit = strrep(FrequencyUnit,'/TimeUnit',['/' localGetSingularTimeUnit(TimeUnit)]);
   end
end
SP = cellfun(@(x)strcmpi(x,'zoh'),pvget(data,'InterSample'),'UniformOutput',false);

sys2 = assignDefaultChannelNames(sys);
lab1 = sys2.OutputName;
lab2 = sys2.InputName;

% Determine whether tab plotting can be used or not
usetabs = (ne > 1);

% Plotting.
import controllib.plot.internal.utils.setColorProperty
if (usetabs)
   % Plot with one tab per experiment.
   figh = gcf;
   clf(figh, 'reset')
   set(figh, 'Name', figname, 'NextPlot', 'replacec');
   set(0, 'CurrentFigure', figh);
   matlab.graphics.internal.themes.figureUseDesktopTheme(figh);
   h = uitabgroup();
   tab = zeros(ne, 1);
   for i = 1:ne
      if isempty(ExperimentName{i})
         ExperimentName{i} = ['Exp' int2str(i)];
      end
      tab(i) = uitab(h, 'title', ExperimentName{i});
      axes('parent', tab(i));
      for j = 1:ny
         subplot(ny, 1, j); cla reset
         if ~isreal(prederr{i}(:, j))
            prederr{i}(:,j) = abs(prederr{i}(:, j));
            predinp{i} = abs(predinp{i});
            isPlottingAbsValue = true();
         else
            isPlottingAbsValue = false();
         end
         line(SamplingInstants{i}, prederr{i}(:, j),'DisplayName',lab1{j})
         if ~FRDFlag
            hold on
            for ku = 1:nu
               if SP{ku,i}
                  s = stairs(SamplingInstants{i}, predinp{i}(:, ku), ...
                     'DisplayName',lab2{ku});
               else
                  s = line(SamplingInstants{i}, predinp{i}(:, ku), ...
                     'DisplayName',lab2{ku});
               end
               setColorProperty(s,'Color',"--mw-color-secondary-hover")
            end
            hold off
         end
         % Set title, xlabel, ylabel
         title(localGetPlotTitle(isSimulation, '', j, OutputName{j}, isPlottingAbsValue));
         if ~isempty(OutputUnit{j})
            ylabel(['y_' int2str(j) ' (' controllibutils.utXlateUnitsString(OutputUnit{j}) ')']);
         else
            ylabel(['y_' int2str(j)]);
         end
         if j == ny
            xlabel(localGetXLabel(isTimeDomainPlot, TimeUnit, FrequencyUnit));
         end
         axis('tight');
         set(gca,'box','on')
         grid on
      end
   end
else
   % Standard plot without tabs
   for i = 1:ne
      if (isempty(ExperimentName{i}) || (ne == 1))
         expname = '';
      else
         expname = ['. ' ExperimentName{i}];
      end
      if (i == 1)
         figh = gcf; clf(figh)
         set(figh, 'Name', [figname expname], 'NextPlot', 'replace');
         set(0, 'CurrentFigure', figh);
         matlab.graphics.internal.themes.figureUseDesktopTheme(figh);
      else
         fig = figure('Name', [figname expname]);
         matlab.graphics.internal.themes.figureUseDesktopTheme(fig);
      end
      if ~isempty(expname)
         expname = [expname(3:end) '. '];
      end
      for j = 1:ny
         subplot(ny, 1, j);
         cla reset
         if ~isreal(prederr{i}(:, j))
            prederr{i}(:,j) = abs(prederr{i}(:, j));
            predinp{i} = abs(predinp{i});
            isPlottingAbsValue = true();
         else
            isPlottingAbsValue = false();
         end
         line(SamplingInstants{i}, prederr{i}(:, j),'DisplayName',lab1{j});
         if ~FRDFlag
            hold on
            for ku = 1:nu
               if SP{ku,i}
                  s = stairs(SamplingInstants{i}, predinp{i}(:, ku), ...
                     'DisplayName',lab2{ku});
               else
                  s = line(SamplingInstants{i}, predinp{i}(:, ku), ...
                     'DisplayName',lab2{ku});
               end
               setColorProperty(s,'Color',"--mw-color-secondary-hover")
            end
            hold off
         end
         % Set title, xlabel, ylabel
         title(localGetPlotTitle(isSimulation, expname, j, OutputName{j}, isPlottingAbsValue));
         if ~isempty(OutputUnit{j})
            ylabel(['y_' int2str(j) ' (' controllibutils.utXlateUnitsString(OutputUnit{j}) ')']);
         else
            ylabel(['y_' int2str(j)]);
         end
         if j == ny
            xlabel(localGetXLabel(isTimeDomainPlot, TimeUnit, FrequencyUnit));
         end
         axis('tight');
         set(gca,'box','on');
         grid on
      end
   end
end
end

function s = localGetPlotTitle(...
   isSimulation, experimentName, outputIndex, outputName, isPlottingAbsoluteValue)
% Construct the internationalized plot title

% Denote the output by its index, or a tuple of form "index: name"
if isempty(outputName)
   outputIdentifier = int2str(outputIndex);
else
   outputIdentifier = [int2str(outputIndex) ': ' outputName];
end

% Determine the message ID and its arguments
hasExperimentName = ~isempty(experimentName);
if isSimulation % simulation
   if hasExperimentName
      msgID = 'Ident:general:msgSimulatedOutputWithExperimentName';
      msgArgs = {experimentName, outputIdentifier};
   else
      msgID = 'Ident:general:msgSimulatedOutput';
      msgArgs = {outputIdentifier};
   end
else % prediction
   if hasExperimentName
      msgID = 'Ident:general:msgPredictedOutputWithExperimentName';
      msgArgs = {experimentName, outputIdentifier};
   else
      msgID = 'Ident:general:msgPredictedOutput';
      msgArgs = {outputIdentifier};
   end
end

% Get the string
s = getString(message(msgID, msgArgs{:}));

% If necessary, add the "(Absolute value)" note at the end
if isPlottingAbsoluteValue
   s = [s ' (' getString(message('Ident:plots:msgAbsoluteValue')) ')'];
end
end

function s = localGetXLabel(isTimeDomainPlot, timeUnit, freqUnit)
% Construct the internationalized x-axis label
if isTimeDomainPlot
   s = getString(message('Ident:plots:msgTime'));
   if ~isempty(timeUnit)
      s = [s ' (' controllibutils.utXlateUnitsString(timeUnit) ')'];
   end
else
   s = getString(message('Ident:plots:msgFrequency'));
   if ~isempty(freqUnit)
      s = [s ' (' controllibutils.utXlateUnitsString(freqUnit) ')'];
   end
end
end

function SingularTimeUnit = localGetSingularTimeUnit(TimeUnit)
% Various TimeUnit options are stores as plural nouns (seconds etc.)
% whereas FrequencyUnit options contain singular time units (rad/second).
%
% See matlab\toolbox\shared\controllib\graphics\+controllibutils\utXlateUnitsString.m
switch TimeUnit
   case {'yoctoseconds', 'zeptoseconds', 'attoseconds', 'femtoseconds', ...
         'picoseconds', 'nanoseconds', 'microseconds', 'milliseconds', ...
         'seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years'}
      SingularTimeUnit = TimeUnit(1:end-1);
   otherwise
      SingularTimeUnit = TimeUnit;
end
end