function [varargout]=plotww3(s,rng,fgcolor,bgcolor,cmap,ax)
%PLOTWW3    Plots WaveWatch III hindcast data
%
%    Usage:    plotww3('file')
%              plotww3('file',rng)
%              plotww3('file',rng,fgcolor,bgcolor)
%              plotww3('file',rng,fgcolor,bgcolor,cmap)
%              plotww3('file',rng,fgcolor,bgcolor,cmap,ax)
%              plotww3(s,...)
%              ax=plotww3(...)
%
%    Description:
%     PLOTWW3('FILE') plots the WaveWatch III hindcast data contained in
%     the GRiB or GRiB2 file FILE averaged across all the records
%     (basically showing the average for the time span of the data in the
%     GRiB file).  One plot per data type (this only matters for wind which
%     means the u/v components are drawn seperately).  If no filename is
%     given a GUI is presented for the user to select a WW3 hindcast file.
%
%     PLOTWW3('FILE',RNG) sets the colormap limits of the data. The default
%     is dependent on the datatype: [0 15] for significant wave heights and
%     wind speed, [0 20] for wave periods, [0 360] for wave & wind
%     direction, & [-15 15] for u & v wind components.
%
%     PLOTWW3('FILE',RNG,FGCOLOR,BGCOLOR) specifies foreground and
%     background colors of the plot.  The default is 'w' for FGCOLOR & 'k'
%     for BGCOLOR.  Note that if one is specified and the other is not, an
%     opposing color is found using INVERTCOLOR.  The color scale is also
%     changed so the noise clip is at BGCOLOR.
%
%     PLOTWW3('FILE',RNG,FGCOLOR,BGCOLOR,CMAP) alters the colormap to CMAP.
%     The default is HSV for wave & wind direction and FIRE for everything
%     else.  The FIRE colormap is adjusted to best match the background
%     color.
%
%     PLOTWW3('FILE',RNG,FGCOLOR,BGCOLOR,CMAP,AX) sets the axes to draw in.
%     This is useful for subplots, guis, etc.  AX must have the same number
%     of elements as S.DATA (as in one plot per data type).  The default
%     creates a new figure.
%
%     PLOTWW3(S,...) plots the WaveWatch III data contained in the
%     structure S created by WW3STRUCT.  The plots average the data across
%     all records for each data type.
%
%     AX=PLOTWW3(...) returns the axes drawn in.
%
%    Notes:
%     - Requires that the njtbx toolbox is installed!
%
%    Examples:
%     % Read the first record of a NOAA WW3 grib file and plot it up:
%     s=ww3struct('nww3.hs.200607.grb',1);
%     ax=plotww3(s);
%
%    See also: PLOTWW3TS, WW3STRUCT, WW3MOV, WW3MAP, WW3MAPMOV, WW3REC,
%              WW3CAT, WW3UV2SA, WW3BAZ2AZ

%     Version History:
%        June 15, 2010 - initial version
%        July  2, 2010 - adjusted oneliner description
%        Aug. 30, 2010 - doc fixes
%        Feb. 11, 2011 - improve axes calls for plotting
%        Feb. 15, 2012 - use ww3struct, doc update
%        May   4, 2012 - allow filename input
%        Jan. 15, 2014 - updated See also list
%        Feb.  5, 2014 - doc update, proper handling of direction
%                        data and nans for ice/land, don't color nans,
%                        colormap input, smart rng/cmap defaults
%
%     Written by Garrett Euler (ggeuler at wustl dot edu)
%     Last Updated Feb.  5, 2014 at 00:40 GMT

% todo:

% check nargin
error(nargchk(0,6,nargin));

% check ww3 struct
valid={'path' 'name' 'description' 'units' 'data' ...
    'lat' 'lon' 'time' 'latstep' 'lonstep' 'timestep'};
if(nargin==0) % gui selection of grib file
    % this does the gui & checks file is valid
    s=ww3struct();
    if(~isscalar(s))
        error('seizmo:plotww3:badWW3',...
            'PLOTWW3 can only handle 1 file!');
    end
elseif(isstruct(s))
    if(~isscalar(s) || any(~ismember(valid,fieldnames(s))))
        error('seizmo:plotww3:badWW3',...
            'S must be a scalar struct generated by WW3STRUCT!');
    end
elseif(ischar(s)) % filename given
    % this checks file is valid
    s=ww3struct(s);
else
    error('seizmo:plotww3:badWW3',...
        'FILE must be a string!');
end

% default/check color limits
if(nargin==1 || isempty(rng)); rng=[nan nan]; end
if(~isreal(rng) || ~isequal(size(rng),[1 2]) || rng(1)>rng(2))
    error('seizmo:plotww3:badRNG',...
        'RNG must be a real-valued 2 element vector as [low high]!');
end

% default/check colors
if(nargin<3)
    fgcolor='w'; bgcolor='k';
elseif(nargin<4)
    if(isempty(fgcolor))
        fgcolor='w'; bgcolor='k';
    else
        bgcolor=invertcolor(fgcolor,true);
    end
else
    if(isempty(fgcolor))
        if(isempty(bgcolor))
            fgcolor='w'; bgcolor='k';
        else
            fgcolor=invertcolor(bgcolor,true);
        end
    elseif(isempty(bgcolor))
        bgcolor=invertcolor(fgcolor,true);
    end
end

% change char to something rgb
if(ischar(fgcolor)); fgcolor=name2rgb(fgcolor); end
if(ischar(bgcolor)); bgcolor=name2rgb(bgcolor); end

% default/check colormap input
defcmap=false;
if(nargin<5 || isempty(cmap)); cmap='default'; defcmap=true; end
if((isnumeric(cmap) && isreal(cmap) ...
        && (ndims(cmap)~=2 || size(cmap,2)~=3 ...
        || ~all(cmap(:)>=0 & cmap(:)<=1))) || (ischar(cmap) ...
        && (ndims(cmap)~=2 || size(cmap,1)~=1)))
    error('seizmo:plotww3:badCMAP',...
        ['COLORMAP must be a colormap function as\n'...
        'a string or a Nx3 RGB triplet array!']);
end

% default/check axes handles
if(nargin<6 || isempty(ax) || numel(ax)~=numel(s.data) ...
        || any(~ishghandle(ax,'axes')))
    makeaxes=true;
    ax=nan(numel(s.data),1);
else
    makeaxes=false;
end

% time string
if(numel(s.time)==1)
    tstring=datestr(s.time,31);
else % >1
    tstring=[datestr(min(s.time),31) ' to ' datestr(max(s.time),31)];
end

% extend map 90deg code
% - for global maps
% - wraps last 90deg to front
extend=false;
if(numel(s.lon)*s.lonstep==360); extend=true; end
if(extend); s.lon=[s.lon(end*3/4+1:end)-360; s.lon]; end

% loop over data types
for i=1:numel(s.data)
    % average data handling ice/land (nans) & direction
    if(size(s.data{i},3)>1)
        if(isequal(s.units{i},'degrees'))
            s.data{i}=azmean(s.data{i},3);
            s.data{i}(s.data{i}<0)=s.data{i}(s.data{i}<0)+360;
        else
            s.data{i}=nanmean(s.data{i},3);
        end
    end
    
    % extend map 90deg code
    % - for global maps
    % - wraps last 90deg to front
    if(extend); s.data{i}=[s.data{i}(:,end*3/4+1:end) s.data{i}]; end
    
    % create plot
    if(makeaxes)
        fh=figure('color',bgcolor,'defaulttextcolor',fgcolor,...
            'defaultaxesxcolor',fgcolor);
        ax(i)=axes('parent',fh);
    end
    
    % plot map
    ih=imagesc(s.lon,s.lat,s.data{i},'parent',ax(i));
    set(ih,'alphadata',~isnan(s.data{i})); % don't color nans
    set(ax(i),'xcolor',fgcolor,'ycolor',fgcolor,'ydir','normal',...
        'color',bgcolor,'fontweight','bold');
    if(all(isnan(rng)))
        if(isequal(s.units{i},'degrees'))
            rng0=[0 360];
        elseif(isequal(s.units{i},'s'))
            rng0=[0 20];
        elseif(any(strcmp(s.description{i},{'U-component of wind' ...
                'V-component of wind' 'u wind' 'v wind'})))
            rng0=[-15 15];
        else
            rng0=[0 15];
        end
    else
        rng0=rng;
    end
    set(ax(i),'clim',rng0);
    
    % labeling
    title(ax(i),...
        {'NOAA WaveWatch III Hindcast' s.description{i} tstring},...
        'fontweight','bold','color',fgcolor);
    xlabel(ax(i),'Longitude (^o)',...
        'fontweight','bold','color',fgcolor);
    ylabel(ax(i),'Latitude (^o)',...
        'fontweight','bold','color',fgcolor);
    
    % colormap
    if(defcmap)
        if(isequal(s.units{i},'degrees'))
            colormap(ax(i),hsv);
        elseif(strcmp(bgcolor,'w') || isequal(bgcolor,[1 1 1]))
            colormap(ax(i),flipud(fire));
        else
            colormap(ax(i),fire);
        end
    else
        colormap(ax(i),cmap);
    end
    
    % colorbar
    c=colorbar('eastoutside','peer',ax(i),...
        'fontweight','bold','xcolor',fgcolor,'ycolor',fgcolor);
    xlabel(c,s.units{i},'fontweight','bold','color',fgcolor)
    axis(ax(i),'equal','tight');
end

% output if wanted
if(nargout); varargout{1}=ax; end

end
