function moviefile = meqmovie(L,LY,varargin)
%MEQMOVIE create matlab movie based on meq LY structure
%
% meqmovie(L,LY,'par','val')
%
%   example: [L,LX,LY] = liuqe(61400,[0.1:1e-1:2]);
%            moviefile = meqmovie(L,LY);
%            moviefile = meqmovie(L,meqxk(LY,1:2:end),'style','fancy','dosave',true,'filename','mymovie')
%
% parameters:
%    'style': { 'plain','fancy','full'}
%           plain: only flux on computational grid
%           fancy: add coils and flux outside grid
%           full:  fancy + evolving time traces
%    'allslices': { true,false } plot all slices or only converged ones
%    'dosave': { true,false} % save movie file or not
%    'filename': string of target .avi file (default: something based on shot/time)
%
% [+MEQ MatlabEQuilibrium Toolbox+] Swiss Plasma Center EPFL Lausanne 2022. All rights reserved.

if isempty(LY), warning('can not plot empty LY'); return; end
if L.P.izgrid
  defaultstyle = 'fancy';
else
  defaultstyle = 'plain';
end

if isnumeric(LY.shot)
  shot= LY.shot(1);
else
  shot = [];
end
defaultfname = sprintf('%s_%d_%02.4f',L.P.tokamak,shot,LY.t(1));

p=inputParser;
p.addParameter('style',defaultstyle,@(x) ischar(x));
p.addParameter('allslices',true,@(x) islogical(x));
p.addParameter('dosave',false,@(x) islogical(x));
p.addParameter('filename',defaultfname,@(x) ischar(x)); 
p.addParameter('decimate',1,@(x) isscalar(x) && isnumeric(x)); % decimate every n frames
p.addParameter('extraquantities',{})
p.addParameter('force',false); % force ploting even for long movies
p.addParameter('framerate',24);
p.KeepUnmatched = true;

parse(p,varargin{:}); P = p.Results;

assert(isstruct(L),'L must be a structure');
assert(isstruct(LY),'LY must be a structure');

% decimate
LY = meqxk(LY,1:P.decimate:numel(LY.t));
  
nt = numel(LY.t);
if nt>240 && ~P.force
  fprintf('Warning! Asking more than %d frames (%f second movie), this may take time... are you sure?',nt,nt/P.framerate)
  if ~contains(lower(input('Y/[N]','s')),'y')
    return
  end
end

if P.dosave
  [writerObj,moviefile] = init_recording(P.filename,P.framerate);
  if isempty(writerObj)
    fprintf('could not init movie writing, exiting\n')
    return
  else
    fprintf('writing movie file: %s\n',moviefile);
  end
else
  moviefile = '';
end

for it=1:nt
  LYt = meqxk(LY,it);
  if ~P.allslices && ~LYt.isconverged, continue;end

  fprintf('plotting t=%f\n',LYt.t);
 switch P.style
   case 'fancy'
    if ~exist('h','var'), h=gca; end
    h = meqplotfancy(L,LYt,'parent',h,...
      p.Unmatched);
    h.Position = [0.08 0.03 0.92 0.90];
   case 'plain'
    cla;
    h = meqplott(L,LYt);
   case 'full'
     if it==1, hax=[]; end
    hax = meqplotfull(L,LYt,'hax',hax);
    h=hax(1);
   otherwise 
     error('unknown style %s',P.style)
  end
  if ~isempty(P.extraquantities)
    if any(contains(P.extraquantities,'Bpx'))
      if exist('hBpx','var') && any(ishandle(hBpx)), delete(hBpx); end 
      [~,hBpx1] = contour(h,L.G.rx,L.G.zx,LYt.Bpx,0:1e-3:0.01,'b-');
      [~,hBpx2] = contour(h,L.G.rx,L.G.zx,LYt.Bpx,0:1e-2:0.1 ,'b--');
      hBpx = [hBpx1;hBpx2];
    end
    if any(contains(P.extraquantities,'Fx'))
      if exist('hFx','var') && any(ishandle(hFx)), delete(hFx); end 
      if exist('hFX','var') && any(ishandle(hFX)), delete(hFX); end
      [~,hFx] = contour(h,L.G.rx,L.G.zx,LYt.Fx,-2:1e-2:2,'k--');
      FX = LYt.FX; FX = FX(~isnan(FX)); if numel(FX)==1, FX=FX*[1 1]; end
      [~,hFX] = contour(h,L.G.rx,L.G.zx,LYt.Fx,FX,'k:');
    end
  end
  %% Text
  if isfield(LYt,'Vloop')
    titstr = sprintf('t=%06.4f,Vloop=%4.2fV',LYt.t,LYt.Vloop);
  elseif isfield(LY,'Ip')
    titstr = sprintf('%s%d,t=%06.4f,Ip=%3.1fkA',L.P.tokamak,shot,LYt.t,LYt.Ip/1e3);
  end
  title(h,titstr)
  %%
  
  if it==1
    axis(h,'off');
    set(gcf,'Color','white')
    set(gcf,'Position',[100,100,400,700])
  end
  
  drawnow; pause(0.01); 
  
  if P.dosave
    fprintf('Writing movie frame: %02d/%02d\n',it,nt)
    frame = getframe(gcf);
    writeVideo(writerObj,frame);
  end
end

if P.dosave
  close(writerObj);
  fprintf('Finished writing movie to: %s\n',moviefile);
end
end

function [writerObj,moviefile] = init_recording(moviefile,framerate)
% initialize recording

if isempty(moviefile)
  [filename,pathname] = uiputfile(moviepath);
else
  filename = moviefile;
  pathname = pwd;
end

% if user aborts here, or other problem, return empty and abort recording
if ~ischar(filename)
  writerObj = [];
  moviefile = '';
  return
else
  % prepare movie object
  moviefile = fullfile(pathname,[filename,'.avi']);
  writerObj = VideoWriter(moviefile,'Motion JPEG AVI');
  set(writerObj,'FrameRate',framerate);
  open(writerObj);
end

end
