function [varargout] = zexst(varargin)
global t zeng zeng2
switch varargin{1}
case 'initial'
%FEA_Ve
%----------------------------------------------------
delete(findobj('type','figure','tag','zexst'))
zexst('DeleteFcn')
%----------------------------------------------------
%Initializing;
t=[];
zeng=[];
zeng2=[];
zeng.temperature=37;
zeng.Iinstim=[];
zeng.Iexstim=[];
zeng.re=50;
zeng.tf=10;%ms
zeng.dt=10;%us
zeng.dtmode=1;          %1=fix, 2=var(coarse) 3=var(fine) 4=var(user defined)
zeng.dtmin =0.00001;    %(ms). 
zeng.dtmax =0.05;       %(ms). 
zeng.dv=[0  0;          %(mv) is used when dt is variable (dtmode = 2-4)
         2 10;          %dtmode=2: [dvmin(mV) dvmax(mV)] - coarse     
         1  5;          %dtmode=3: [dvmin(mV) dvmax(mV)] - fine          
         2 10];         %dtmode=4: [dvmin(mV) dvmax(mV)] - the GUI is not implemented yet.
zeng.dtstart=[0;        %(us) used when dt is variable (dtmode = 2-4) 
              1;
              0.2;
              1];
%---------------------------------------------------
zeng2.file='Ex_03_simple_axon.m';
zeng2.method='V_backward';
zeng2.cd=cd;
zeng2.FEA=[];           %use for Finite Element Analysis
zeng2.FILESEP=filesep;
zeng2.setup=[];
zeng2.var=[];
zeng2.varlist=cell(1);
zeng2.notreadytorun=0; %set it to 0 to stop the "Calculate" when there is an error in creating dummy.

zeng2.options.vestim=1;      %1) calculated or 2) imported
zeng2.backup.Iexstim=[];
zeng2.amp=1;             %zeng2.amp is multiplied to the amplitude of "both Ve and Iin stimulators".
                        %It is convinient for threshold detection.
                        %For Iin(WaveForm),  zeng2.amp is used at zrun
zeng2.rundisp =1;       %1=show the cal-progress window and the cal time.
                        %0=do not show anything. Good for running analysis
zeng2.singular=0;       %for detecting the singular                        
%---------------------------------------------------
ScreenSize=get(0,'ScreenSize');
FG_Size=[5 ScreenSize(4)-30-40 220 30];
exst.figure = figure('Color',[0.8 0.8 0.8], ...
   'PaperUnits','points', ...
   'DeleteFcn','zexst(''DeleteFcn'');',...
   'Position',FG_Size, ...
   'tag','zexst', ...
   'menu','none',...
   'Name','NeuroCal',...
   'NumberTitle','off',...
   'Resize','off',...
   'ToolBar','none');
set(exst.figure,'position',FG_Size);% stupid, but I need it for WinXP
exst.text.file = uicontrol('Parent',exst.figure, ...
	'Units','pixel', ...
    'BackgroundColor',[0.8 0.8 0.8], ...
    'HorizontalAlignment','left',...
	'ListboxTop',0, ...
	'Position',[5 5 200 22], ...
	'String',['Model : ' zeng2.file], ...
	'Style','text', ...
   'Tag','StaticText1');
exst.menu.file(1)=uimenu('parent',exst.figure,'label','File');
exst.menu.file(2)=uimenu('parent',exst.menu.file(1),'label','Open model'   ,'callback','zexst(''open model file'')');
exst.menu.file(3)=uimenu('parent',exst.menu.file(1),'label','Open Analysis','callback','zexst(''Open Analysis'')');

exst.menu.setting(1)=uimenu('parent',exst.figure,'label','Setting');
exst.menu.setting(2)=uimenu(exst.menu.setting(1),'label','Time'              ,'callback','gui_time(''initial'',gcf)');
exst.menu.setting(3)=uimenu(exst.menu.setting(1),'label','Environment'       ,'callback','gui_environment(''initial'',gcf)');
exst.menu.setting(4)=uimenu(exst.menu.setting(1),'label','Parameters'        ,'callback','gui_var(''initial'',gcf)');
exst.menu.setting(5)=uimenu(exst.menu.setting(1),'label','Channels'          ,'callback','gui_channel(''initial'',gcf)');
exst.menu.setting(6)=uimenu(exst.menu.setting(1),'label','Intracellular Stim','callback','gui_Iinstim(''initial'')');
exst.menu.setting(7)=uimenu(exst.menu.setting(1),'label','Extracellular Stim','callback','gui_Iexstim(''initial'')');

exst.menu.graph(1)=uimenu('parent',exst.figure,'label','Graph');
exst.menu.graph(2)=uimenu('parent',exst.menu.graph(1),'label','2D-Viewer vs time' ,'callback','zview2dt(''initial'',gcf)');
exst.menu.graph(3)=uimenu('parent',exst.menu.graph(1),'label','2D-Viewer vs space','callback','zview2ds(''initial'',gcf)');
exst.menu.graph(4)=uimenu('parent',exst.menu.graph(1),'label','3D-Viewer'         ,'callback','zview3d(''initial'',gcf)');

exst.menu.opt(1)=uimenu('parent',exst.figure,'label','Options');
exst.menu.opt(2)=uimenu('parent',exst.menu.opt(1),'label','Ve-Calculated' ,'callback','zexst(''change options'')','tag','vestim','userdata',1);
exst.menu.opt(3)=uimenu('parent',exst.menu.opt(1),'label','Ve-Imported'   ,'callback','zexst(''change options'')','tag','vestim','userdata',2);
set(findobj(exst.menu.opt,'tag','vestim','userdata',zeng2.options.vestim),'checked','on')

exst.menu.about=uimenu('parent',exst.figure,'label','About','callback','zexst(''about'')');

set(exst.figure,'userdata',exst);
zexst('open model file',zeng2.file)
gui_time('initial',exst.figure)
gui_var('initial',exst.figure);
zview3d('initial',exst.figure)
%----------------------------------------------------------
case 'change options'
    if nargin==1
        exst=get(gcbf,'userdata');
        Tag=get(gcbo,'tag');
        Setto=get(gcbo,'userdata');
    else
        Temp=findobj(0,'type','figure','Name','NeuroCal','tag','zexst');
        exst=get(Temp,'userdata');
        Tag=varargin{2};
        Setto=varargin{3};
    end
    Temp=get(findobj(exst.menu.opt,'tag',Tag,'checked','on'),'userdata');
    if Temp{1}==Setto
        return
    end
    set(findobj(exst.menu.opt,'tag',Tag),'checked','off')
    set(findobj(exst.menu.opt,'tag',Tag,'userdata',Setto),'checked','on')
    eval(['zeng2.options.' Tag '=Setto;'])
    switch Tag
        case 'vestim'
            temp1=findobj('type','figure','tag','gui_Iexstim');
            temp2=findobj('type','figure','tag','gui_var');
            switch Setto
                case 1 %calculated
                    set(findobj(temp1,'tag','xyz'),'enable','on')
                    set(findobj(temp2,'tag','xyz'),'enable','on')
                case 2 %imported
                    set(findobj(temp1,'tag','xyz'),'enable','off')
                    set(findobj(temp2,'tag','xyz'),'enable','off')
                otherwise
                    zexst('err','Err in Setting Option for Ve')
                end
        end
case 'Open Analysis'
    exst=get(gcbf,'userdata');
    [Filename Path]=uigetfile([zeng2.cd zeng2.FILESEP 'Analysis' zeng2.FILESEP '*.m']);
    if ~strcmp('0',num2str(Filename))
        temp=find(Filename=='.');
        if isempty(temp)
            feval(Filename,'initial',gcbf)    
        else
            feval(Filename(1:(temp(1)-1)),'initial',gcbf)    
        end
    end
case 'DeleteFcn'
    delete(findobj('type','figure','tag','zview2dt'))
    delete(findobj('type','figure','tag','zview2ds'))
    delete(findobj('type','figure','tag','zview3d'))
    delete(findobj('type','figure','tag','gui_Iinstim'))
    delete(findobj('type','figure','tag','gui_Iexstim'))
    delete(findobj('type','figure','tag','gui_envi'))
    delete(findobj('type','figure','tag','gui_time'))
    delete(findobj('type','figure','tag','gui_var'))
    delete(findobj('type','figure','tag','gui_channel'))
    delete(findobj('type','figure','tag','ZengAnalysis'))

case 'open model file'
    if nargin==1
        exst=get(gcbf,'userdata');
        [Filename Path]=uigetfile([zeng2.cd zeng2.FILESEP 'model' zeng2.FILESEP '*.m']);
    else %=2
        exst=findobj('type','figure','tag','zexst','name','NeuroCal');
        exst=get(exst,'userdata');
        Filename=varargin{2};
        Path=[];
    end
    if ~strcmp('0',num2str(Filename))
        tempzeng=Filename(1)+0;
        if (tempzeng>=65&tempzeng<=90) | (tempzeng>=97&tempzeng<=122)
        else
            zexst('err',['Please rename the file name to something else beginning with a charactor a-z']);
            return
        end
	    dot=find(Filename=='.');
        if ~isempty(dot)
	        Filename=Filename(1:(dot-1));
        end
        zeng2.file=Filename;
        set(exst.text.file,'String',['Model : ' Filename ])
        %--------------------------------
        %clear varibles
        if ~isempty(zeng2.var)
    		for temp=1:length(zeng2.varlist)
        		clear('global',zeng2.varlist{temp})
     		end
	    end %if ~isempty(zeng2.var)
        %-------------------------------------------------------
        zeng2.var=[];
        zeng2.varlist=cell(1);
        zeng2.dummyvar=[]; %for view2-3d
        zeng2.dummymodel=[];
        zeng2.dummymodelindex=[];
        zeng2.setup=[];
        zeng2.setup.connect=[];%Needed because [zeng.setup.connect; a b c d ] will be used in CONNECT
        zeng2.setup.stimIin=[];
        zeng2.setup.stimVe=[];
        zeng2.setup.n_para=0; % Good for checking if you have created the neural network
      
        zeng.Iinstim=[];
        zeng.Iexstim=[];
        t=[];
        
        if isempty(Path)
            eval(Filename)
        else
            tempzeng=length(Path);
            if Path(tempzeng)=='\'
                Path(tempzeng)=[];
            end
            addpath(Path)
            eval(Filename)
        end
        create_dummyvar
        zexst('Update GUI')
    end %if ~strcmp('0',num2str(Filename))
case 'Update GUI'
   %update  Time----------------------------------------------------------------------------
   tempzeng=findobj('type','figure','tag','gui_time');
   if ~isempty(tempzeng)
      settime=get(tempzeng,'userdata');
      set(settime.pop.dt ,'value',zeng.dtmode)
      set(settime.edit.tf,'string',num2str(zeng.tf))
      set(settime.edit.dt,'string',num2str(zeng.dt))
   end

   %update  environment----------------------------------------------------------------------------
   tempzeng=findobj('type','figure','tag','gui_envi');
   if ~isempty(tempzeng)
      envi=get(tempzeng,'userdata');
      set(envi.edit.temp,'string',num2str(zeng.temperature))
      set(envi.edit.re  ,'string',num2str(zeng.re))
   end
   %update View2d 3d----------------------------------------------------------------------------
   close(findobj('type','figure','name','2D-Time : Plot'));
   close(findobj('type','figure','name','2D-Space : Plot'));
   close(findobj('type','figure','name','3D-Viewer : Plot'));
   tempzeng=[findobj('type','figure','tag','zview2dt')];
   if ~isempty(tempzeng)
      for i=1:length(tempzeng)
         view=get(tempzeng(i),'userdata');
         view.plotvariable.var=[]; %[para var seg]
         view.plotvariable.legend=cell(0);    
         set(tempzeng(i),'userdata',view);
         %--------------------------------------------------------
         %important
         set(get(view.axes,'children'),'DeleteFcn','')
         axes(view.axes)
         legend off
         delete(get(view.axes,'children'))
         %--------------------------------------------------------
         zview2dt('plot',tempzeng(i))
      end
   end
   tempzeng=[findobj('type','figure','tag','zview2ds')];
   if ~isempty(tempzeng)
      for i=1:length(tempzeng)
         view=get(tempzeng(i),'userdata');
         view.plotvariable.var=[]; %[para var length]
         view.plotvariable.legend=cell(0);    
         set(tempzeng(i),'userdata',view);
         %--------------------------------------------------------
         %important
         set(get(view.axes,'children'),'DeleteFcn','')
         axes(view.axes)
         legend off
         delete(get(view.axes,'children'))
         %--------------------------------------------------------
         zview2ds('plot',tempzeng(i))
      end
   end
   tempzeng=findobj('type','figure','tag','zview3d');
   if ~isempty(tempzeng)
      for i=1:length(tempzeng)
         view=get(tempzeng(i),'userdata');
         view.plotvariable.var=[]; %[para var seg]
         set(tempzeng(i),'userdata',view);
         delete(get(view.axes,'children'))
         zview3d('plot',tempzeng(i))
      end
   end
   %update Iinstim----------------------------------------------------------------------------
   tempzeng=findobj('type','figure','tag','gui_Iinstim');
   if ~isempty(tempzeng)
      temppo=get(tempzeng,'position');
      close(tempzeng)
      if ~isempty(zeng.Iinstim)
         gui_Iinstim('initial',temppo)
      end
   end
   %update Iexstim----------------------------------------------------------------------------
   tempzeng=findobj('type','figure','tag','gui_Iexstim');
   if ~isempty(tempzeng)
      temppo=get(tempzeng,'position');
      close(tempzeng)
      if ~isempty(zeng.Iexstim)
         gui_Iexstim('initial',temppo)
      end
   end
   %update setting:parameters----------------------------------------------------------------------------
   tempzeng=findobj('type','figure','tag','gui_var');
   if ~isempty(tempzeng)
      for i=1:length(tempzeng)
         gui_var('update',tempzeng(i),1);
      end
   end
   %update setting:Channel----------------------------------------------------------------------------
   tempzeng=findobj('type','figure','tag','gui_channel');
   if ~isempty(tempzeng)
      for i=1:length(tempzeng)
         gui_channel('update',tempzeng(i),1);
      end
   end
case 'calculate'
   %To disable the buttons
   %set(findobj('type','uicontrol','tag','Pushbutton'),'enable','off')
   %-----------
   if nargin==2         % Called by Find_Ith for detect the firing
       varargout{1}=-1; % -1=Bad setting, 0=not fired, 1=fired
   end
   %-----------------------------------
   %Before run

   zeng2.notreadytorun=0;
   create_initial
   if zeng2.notreadytorun
        set(findobj('type','uicontrol','tag','Pushbutton'),'enable','on')
        return
   end
   create_dummyvar
   if zeng2.notreadytorun
        set(findobj('type','uicontrol','tag','Pushbutton'),'enable','on')
        return
   end
   create_setting   
   if zeng2.notreadytorun
        set(findobj('type','uicontrol','tag','Pushbutton'),'enable','on')
        return
   end
   create_matrix
   if zeng2.notreadytorun
        set(findobj('type','uicontrol','tag','Pushbutton'),'enable','on')
        return
   end
   create_dummymodel
   if zeng2.notreadytorun
        set(findobj('type','uicontrol','tag','Pushbutton'),'enable','on')
        return
   end
   create_stimIin
   if zeng2.notreadytorun
        set(findobj('type','uicontrol','tag','Pushbutton'),'enable','on')
        return
   end
   create_stimVe
   if zeng2.notreadytorun
        set(findobj('type','uicontrol','tag','Pushbutton'),'enable','on')
        return
   end
    %ckeck dt
    if isempty(zeng.dt)| zeng.dt<(zeng.dtmin*1000) | zeng.dt>(zeng.dtmax*1000) | ~isreal(zeng.dt)
        zexst('err',['"dt" needs to be in between ' num2str(zeng.dtmin*1000) '-' num2str(zeng.dtmax*1000) 'us !!!, You know?']);
        set(gcbo,'enable','on')
        return
    end

   %check pulse width ----------------------------------
   if zeng.dtmode==1 %fix time step
       if isempty(zeng.Iinstim)
       else
           tempzeng=zeng.dt/1000*5;
           for i=1:length(zeng.Iinstim)
               if zeng.Iinstim(i).dur<tempzeng & isnumeric(zeng.Iinstim(i).amp)
                   zexst('err',['The time step has to be' char(13) 'at least 5 times smaller than the smallest pulse width.']);
                   set(gcbo,'enable','on')
                   return
               end
           end
       end
       if isempty(zeng.Iexstim)
       else
           tempzeng=zeng.dt/1000*5;
           for i=1:length(zeng.Iexstim)
               if zeng.Iexstim(i).dur<tempzeng & isnumeric(zeng.Iexstim(i).amp)
                   zexst('err',['The time step has to be' char(13) 'at least 5 times smaller than the smallest pulse width.']);
                   set(gcbo,'enable','on')
                   return
               end
           end
       end
   end
   %----------------------------------
   zeng2.singular=0;
   if nargin==1     %normal calculationg in Neurocal
        zrun
        if ~isempty(find(abs(zeng2.dummyvm)>7000))
            zeng2.singular=1;
            disp(['---Attention-------------------------------------------------------'])
            disp(['Singular detected: This can caused by a large stimulation amplitude.'])
            disp(['For Iinstim, the amp should be lower than 10uA.'])
            disp(['For Iexstim, make sure the coordinate of the stimulator is not right at a node.'])
            disp(['-------------------------------------------------------------------'])
            return
        end
        zdummy_return
        zcal_i
   elseif nargin==2 %detecting the firing
        varargout{1}=zrun(varargin{2}); %varout =0(not fired), 1(fired) - varin=[Detect_Start(us)  Detect_Threshold(mV)]
        if ~isempty(find(abs(zeng2.dummyvm)>7000))
            zeng2.singular=1;
            disp(['---Attention-------------------------------------------------------'])
            disp(['Singular detected: This can caused by a large stimulation amplitude.'])
            disp(['For Iinstim, the amp should be lower than 10uA.'])
            disp(['For Iexstim, lower the stimulation amplitude and make sure the coordinate of the stimulator is not right at a node.'])
            disp(['-------------------------------------------------------------------'])
            varargout{1}== -1;
            return
        end
   end
   %----------------------------------
   %To enable the button
    set(findobj('type','uicontrol','tag','Pushbutton'),'enable','on')
    %update View after the calculation------------------------------------------------------
    temp=findobj('type','figure','tag','zview2dt');
    if ~isempty(temp)
        for v=1:length(temp)
            zview2dt('update',temp(v));
            temp1=get(temp(v),'userdata');
            temp2=findobj('type','figure','Tag',[num2str(temp1.figure) num2str(temp1.axes)]);
            if ~isempty(temp2)
                zview2dt('update-segment',temp2)
            end        
        end
    end
    temp=findobj('type','figure','tag','zview2ds');
    if ~isempty(temp)
        for v=1:length(temp)
            zview2ds('update',temp(v));
        end
    end
    temp=[findobj('type','figure','tag','zview3d')];
    if ~isempty(temp)
        for v=1:length(temp)
            zview3d('update',temp(v));
        end
    end
   %----------------------------------
case 'err'
   ScreenSize=max(reshape(get(0,'screensize'),2,2)');
   E = dialog('name','Error',...
      'tag','ZengError');
   set(E,'position',[ScreenSize(1)/2-320/2 ScreenSize(2)/2-160/2 320 160]);
   Temp.FG_Size=get(E,'position');
   uicontrol('Parent',E, ...
      'BackgroundColor',get(E,'Color'), ...
      'fontsize',12,...
      'fontweight','bold',...
      'Position',[1 120 320 20], ...         'String','Are you nuts !!!', ...
      'String','Hey man !!!', ...
      'Style','text');
   uicontrol('Parent',E, ...
      'BackgroundColor',get(E,'Color'), ...
      'HorizontalAlignment','center',...
      'Position',[1 40 Temp.FG_Size(3) 60], ...
      'String',varargin{2}, ...
      'Style','text');
   uicontrol('Parent',E, ...
	'BackgroundColor',[0.85 0.8 0.75], ...
      'callback','close',...
      'Units','pixel', ...
      'Position',[135 15 57.75 24],...
      'string','OK');
case 'about'
    ScreenSize=max(reshape(get(0,'screensize'),2,2)');
    About = dialog('name','About Exstim');
    set(About,'Position',[ScreenSize(1)/2-320/2 ScreenSize(2)/2-160/2 320 200]);
    FG_Size=get(About ,'position');
    uicontrol('Parent',About , ...
      'BackgroundColor',get(About ,'Color'), ...
      'fontsize',12,...
      'fontweight','bold',...
      'ForegroundColor',[0 0 1 ],...
      'Position',[1 140 320 50], ...       
      'String',['Neural Engineering Center' char(13) 'Case Western Reserve University'], ...
      'Style','text');
    uicontrol('Parent',About , ...
      'BackgroundColor',get(About ,'Color'), ...
      'fontsize',14,...
      'fontweight','normal',...
      'ForegroundColor',[1 0 0 ],...
      'Position',[1 120 320 20], ...      
      'String',['nec.cwru.edu'], ...
      'Style','text');
    uicontrol('Parent',About , ...
      'BackgroundColor',get(About ,'Color'), ...
      'fontsize',10,...
      'fontweight','bold',...
      'ForegroundColor',[0 0 1 ],...
      'Position',[1 60 320 50], ...       
      'String',['Version 1.0'], ...
      'Style','text');
    uicontrol('Parent',About , ...
      'BackgroundColor',get(About ,'Color'), ...
      'fontsize',10,...
      'fontweight','normal',...
      'ForegroundColor',[0 00 0 ],...
      'Position',[1 35 320 50], ...       
      'String',['Zeng Lertmanorat (Thai boy)' char(13) 'zengzeng@hotmail.com'], ...
      'Style','text');
    uicontrol('Parent',About , ...
      'callback','close',...
      'Units','pixel', ...
      'Position',[135 10 57.75 24],...
      'string','OK');
end %switch