%
%---------------------------------------------------------------------  
% function [mirror] = FT_init_mirror(varargin)
% 
% Matlab function that creates a structure `mirror' storing 
% parameter of the optical component `mirror' resembling a 
% single optical surface.
%
% Usage for example:
%  mirror=FT_init_mirror('R',0.9)
% or
%  mirror=FT_init_mirror('R',0.9,'Rc',3500)
%
% The following (optional) parameters can be given by the user:
% R - power reflectivity
% r - amplitude reflectivity
% T - power transmission
% t - amplitude transmission
% L - power loss
% Rc - Radius of curvature (can be given as Rc or as Rcx, Rcy) [m]
% alpha - angle of incidenece [deg] (will be converted to radian by this function)
% diameter - diameter of the mirror [m]
% M - mirror mass [kg]
% n - index of refraction of mirror material (only used for mirror maps)
% name - string
%
% The function computes the remaining values for R,T,r,t,L from the ones provided
% (i.e. L=1-T-R). If no values are provided by the user the structure the
% following defaults:
% R = 1
% r = 1
% T = 0
% t = 0
% Loss = 0
% Rc = [Inf; Inf] (flat mirror)
% alpha = 0 rad
% diameter = Inf
% M = Inf
% n = 1.45
% name =''
% mirror - 1 (this field is used simply to identify the structure as a mirror)
%
% Part of the SimTools package
% Andreas Freise, 26.12.2009 afreise@googlemail.com
%---------------------------------------------------------------------  
%

% Description: Creates "mirror" structure for storing parameters of a mirror
% Keywords: init, mirror, structure, parameter

function [mirror] = FT_init_mirror(varargin)

   baseid='init_mirror';

   %%% initialise `mirror' structure
   mirror.R=1.0;
   mirror.r=1.0;
   mirror.T=0.0;
   mirror.t=0.0;
   mirror.Loss=0.0;
   mirror.Rc=1.0./zeros(2,1,'double');
   mirror.alpha=0.0;
   mirror.diameter=1.0./0.0;
   mirror.M=1.0./0.0;
   mirror.n=1.45;
   mirror.name='';
   mirror.mirror=1;
   
   T_set=0;
   R_set=0;
   r_set=0;
   t_set=0;
   L_set=0;
   Rcx_set=0;
   Rcy_set=0;
   
   %%% parse input arguments
   if nargin > 0
     % check which calling syntax is used
     actual_n=1;
     while actual_n<=nargin-1
       switch varargin{actual_n}
        case 'R',
         mirror.R = varargin{actual_n+1};
         R_set=1;
        case 'r',
         mirror.r = varargin{actual_n+1};
         r_set=1;
        case 'T',
         mirror.T = varargin{actual_n+1};
         T_set=1;
        case 't',
         mirror.t = varargin{actual_n+1};
         t_set=1;
        case 'L',
         mirror.Loss = varargin{actual_n+1};
         L_set=1;
        case 'Rc',
         mirror.Rc(:) = varargin{actual_n+1};
         Rcx_set=1;
         Rcy_set=1;
        case 'Rcx',
         mirror.Rc(1) = varargin{actual_n+1};
         Rcx_set=1;
        case 'Rcy',
         mirror.Rc(2) = varargin{actual_n+1};
         Rcy_set=1;
        case 'alpha',
         mirror.alpha = varargin{actual_n+1};
        case 'M',
         mirror.M = varargin{actual_n+1};
        case 'n',
         mirror.n = varargin{actual_n+1};
        case 'diameter',
         mirror.diameter = varargin{actual_n+1};
        case 'name',
         mirror.name = varargin{actual_n+1};
        otherwise ,
          msgid=[baseid,':checkinarg'];
          result=sprintf(['Unknown option: ', varargin{actual_n}, '.\n']);
          error(msgid,result);
       end;   
       actual_n=actual_n+2;
     end;  
   end
   
   %%% check input arguments
   if (mirror.T<0 ||mirror.t<0 ||mirror.R<0 ||mirror.r<0)
     msgid=[baseid,':checkinarg'];
     result=sprintf('R,T,r or t cannot be negative.\n');
     error(msgid,result);
   end

   if (mirror.n<0 ||mirror.Loss<0)
     msgid=[baseid,':checkinarg'];
     result=sprintf('n or L cannot be negative.\n');
     error(msgid,result);
   end

   if (mirror.diameter<0)
     msgid=[baseid,':checkinarg'];
     result=sprintf('mirror diameter cannot be negative.\n');
     error(msgid,result);
   end

   if (mirror.M<=0)
     msgid=[baseid,':checkinarg'];
     result=sprintf('mirror mass must be >0.\n');
     error(msgid,result);
   end

   
   if (bitand(Rcx_set,Rcy_set)==0 && bitor(Rcx_set,Rcy_set)==1)
     msgid=[baseid,':checkinarg'];
     result=sprintf('Please specify Rcx and Rcy (or a common Rc).\n');
     error(msgid,result);
   end
   
   if (~ischar(mirror.name))
     msgid=[baseid,':checkinarg'];
     result=sprintf('mirror name must be a string.\n');
     error(msgid,result);
   end   
   
   if (T_set && t_set)
     msgid=[baseid,':checkinarg'];
     result=sprintf('T and t are mutually exclusive.\n');
     error(msgid,result);
   end
   
   if (R_set && r_set)
     msgid=[baseid,':checkinarg'];
     result=sprintf('R and r are mutually exclusive.\n');
     error(msgid,result);
   end
   
   if (t_set)
     mirror.T=mirror.t^2;
     T_set=1;
   end
   if (r_set)
     mirror.R=mirror.r^2;
     R_set=1;
   end
   

   if (T_set && L_set && R_set && mirror.T+mirror.Loss+mirror.R~=1)
     msgid=[baseid,':checkinarg'];
     result=sprintf('If T,R and L are given explicitly, they must be set such that R+T+L=1.\n');
     error(msgid,result);
   end

   if (mirror.T>1 || mirror.R>1 || mirror.Loss>1)
     msgid=[baseid,':checkinarg'];
     result=sprintf('T,R and L cannot be larger than 1.\n');
     error(msgid,result);
   end
 
   if (L_set)
     if (R_set && ~T_set)
       if (mirror.R+mirror.Loss>1)
         msgid=[baseid,':checkinarg'];
         result=sprintf('R+L cannot be larger than 1.\n');
         error(msgid,result);
       end
       mirror.T=1-mirror.Loss-mirror.R;
     elseif (~R_set && T_set)
       if (mirror.T+mirror.Loss>1)
         msgid=[baseid,':checkinarg'];
         result=sprintf('T+L cannot be larger than 1.\n');
         error(msgid,result);
       end
       mirror.R=1-mirror.Loss-mirror.T;
     elseif (~R_set && ~T_set)
       mirror.R=1-mirror.Loss;
       mirror.T=0;
     end
   else
     mirror.L=oss1-mirror.T-mirror.R;
   end
   
   if (mirror.T+mirror.R+mirror.Loss>1)
     msgid=[baseid,':checkinarg'];
     result=sprintf('T+R+L cannot be larger than 1.\n');
     error(msgid,result);
   end

   mirror.t=sqrt(mirror.T);
   mirror.r=sqrt(mirror.R);
   
   return