function [OutImageCell,OutMatrixCell]=imshift_fits(InImages,OutImages,Shift,varargin)
%--------------------------------------------------------------------------
% imshift_fits function                                            ImBasic
% Description: Coordinates transformation and image registration of images
%              by a shift (see also: imtrans_fits.m).
% Input  : - List of input FITS images (see create_list.m for details).
%            Alternatively, this can be a cell array in which each cell
%            contains the image in a matrix form, or a matrix.
%          - Lits of output FITS images (see create_list.m for details).
%            If empty matrix will use the input images, along with the
%            'OutPrefix' and 'OutDir' parameters to determine
%            the output image names.
%            If empty matrix than the input images must be in FITS format.
%          - Shift in [X, Y] coordinate per each input image.
%            Alternaively, if this is a structure or an array structure
%            then it is used as a matlab transformation structure,
%            see maketform.m for details.
%          * Arbitrary number of argument pairs: ...,keyword,value,...
%            Where each keyword is followd by a value.
%            The following keywords are available:
%            'OutPrefix' - Add prefix before output image names,
%                          default is empty string (i.e., '').
%            'OutDir'    - Directory in which to write the output images,
%                          default is empty string (i.e., '').
%            'AddHead'   - Cell array with 3 columns containing additional
%                          keywords to be add to the header.
%                          See cell_fitshead_addkey.m for header structure
%                          information. Default is empty matrix.
%            'CopyHead'  - Copy header from input image {'y'|'n'}, default is 'y'.
%            'DataType'  - Output data type (see fitswrite.m for options), 
%                          default is float32.
%            'DelDataSec'- Delete DATASEC keyword from output image header
%                          {'y'|'n'}, default is 'n'.
%            'Save'      - Save output images {'y'|'n'|'fits','mat'},
%                          default is 'y', which saves a fits file.
%                          If 'n' then will return only a matrix images.
%            
%            'FileType'  - Input file type {'FITS'|'mat'}, default is 'FITS'.
%                          This keyword is overrid if input is a matrix.
%            'FitsReadPar'-A cell array of additional parameters to pass to
%                          fitsread.m (e.g., {2}; which means read the image
%                          from the second extension.
%                          Default is {}.
%            'Section'   - Image section on which to operate....
%            'SectionType'-...
%            'XData'      - ... default is to use the size of the first image
%                               +/- the min/max shifts.
%--------------------------------------------------------------------------


if (isnumeric(Shift)),
   ShiftX = Shift(:,1);
   ShiftY = Shift(:,2);

   MinShiftX = min(ShiftX);
   MaxShiftX = max(ShiftX);
   MinShiftY = min(ShiftY);
   MaxShiftY = max(ShiftY);
else
   MinShiftX = 0;
   MaxShiftX = 2048;
   MinShiftY = 0;
   MaxShiftY = 2048;
end

% All im*_fits functions
DefV.OutPrefix   = '';
DefV.OutDir      = '';
DefV.DelDataSec  = 'n';
DefV.CopyHead    = 'y';
DefV.AddHead     = [];
DefV.DataType    = 'float32';
DefV.Save        = 'y';      % {'n' | 'y' | 'FITS' | 'mat'} 
DefV.FileType    = 'FITS';   % {'FITS' | 'mat'}
DefV.FitsReadPar = {};
DefV.Section     = [];
DefV.SectionType = 'boundry';
% specific parameters for imtrans_fits.m
DefV.XData       = [];
DefV.YData       = [];
InPar = set_varargin_keyval(DefV,'y','use',varargin{:});


   
[InImagesCell,InMatCell,IsNumeric,Nim] = imget_fits(InImages,...
                                                    'FileType',InPar.FileType,...
                                                    'ReadAll','n');

%--- Deal with specific parameters ---                                         
if (isempty(InPar.XData)),
  % get image size from first image in the list
  if (IsNumeric),
     [NAXIS2, NAXIS1] = size(InMatCell{1});
  else
     KeywordVal = get_fits_keyword(InImagesCell{1},{'NAXIS1','NAXIS2'});
     NAXIS1 = KeywordVal{1};
     NAXIS2 = KeywordVal{2};
  end
  InPar.XData = [min(MinShiftX,1), NAXIS1+max(MaxShiftX,1)];
  InPar.YData = [min(MinShiftY,1), NAXIS2+max(MaxShiftY,1)];
end
 
if (IsNumeric==1 && isempty(OutImages) && ~strcmpi(InPar.Save,'n'))
    error('Save=y option while input is a numeric matrix is possible only when OutImages are specified');
end
switch lower(InPar.Save)
    case {'y','fits','mat'}
        [OutImageCell] = prep_output_images_list(InImages,OutImages,varargin{:});
    otherwise
        OutImageCell = [];
end
        
HeaderInfo = [];
if (nargout>1),
   OutMatrixCell = cell(Nim,1);
end

for Iim=1:1:Nim,
   HeaderInfo = [];

   %--- read image ---
   if (IsNumeric==1),
      InImage = InMatCell{Iim};
   else
      [~,InImage] = imget_fits(InImagesCell{Iim},...
                               'FileType',InPar.FileType,...
                               'FitsReadPar',InPar.FitsReadPar,...
                               'Section',InPar.Section,...
                               'SectionType',InPar.SectionType,...
                               'ReadAll','y',...
                               'Cell','n');
      switch lower(InPar.FileType)
       case 'fits'
          ImHead = fitsinfo(InImagesCell{Iim});
          HeaderInfo = ImHead.PrimaryData.Keywords;
       otherwise
          HeaderInfo = [];
      end                   
   end
   
   %---------------------
   %--- work on image ---
   %---------------------
   
   if (isnumeric(Shift)),
      AffineMatrix = [1 0 ShiftX(Iim); 0 1 ShiftY(Iim); 0 0 1];
      TForm = maketform('affine',AffineMatrix');
   else
      TForm = Shift(Iim);
   end
   RSamp = makeresampler('cubic','bound');
   OutImage = imtransform(InImage,TForm,RSamp,...
            'FillValues',NaN,'XData',InPar.XData,'YData',InPar.YData);
   

   
   
   
   %--- write image ---
   % assume output matrix is in: OutImage
   % and outoput image name is in: OutImageCell{Iim}
   
   if (nargout>1),
       OutMatrixCell{Iim} = OutImage;
   end
   
   switch lower(InPar.Save)
       case {'y','fits'}
           %------------------------
           %--- write FITS image ---
           %------------------------

           %--- Add to header comments regarding file creation ---
           [HeaderInfo] = cell_fitshead_addkey(HeaderInfo,...
                                       Inf,'COMMENT','','Created by imtrans_fits.m written by Eran Ofek');


           %--- Modify WCS keywords if needed ---
           % TBD!!!!!                                   
                                   
           if (~isempty(InPar.AddHead)),
              %--- Add additional header keywords ---
              HeaderInfo = [HeaderInfo; InPar.AddHead];
           end

           switch lower(InPar.DelDataSec)
              case 'n'
                  % do nothing
              case 'y'
                  % delete DATASEC keyword from header
                  [HeaderInfo] = cell_fitshead_delkey(HeaderInfo,'DATASEC');
              otherwise
                   error('Unknown DelDataSec option');
           end

           %--- Write fits file ---
           fitswrite(OutImage,OutImageCell{Iim},HeaderInfo,InPar.DataType);
        
       case 'mat'
           %----------------------
           %--- wtite mat file ---
           %----------------------
           save(OutImageCell{Iim},'OutImage');
   
      
       case 'n'
           % do not write output
   
       otherwise
           error('Unknown Save option');
     
   end
end
   
   
