!----------------------------------------------
!  USpack Module
!----------------------------------------------
module uspack
  use dcl_common
  real, private :: xsec0, ysec0, xfac0, yfac0, xoff0, yoff0
  character(len=32) :: xttl0, yttl0, xuni0, yuni0
  private ::   SetFactor,  SetOffset,  SetSection,  SetTitle,  SetUnit, &
           & ResetFactor,ResetOffset,ResetSection,ResetTitle,ResetUnit
  contains

!----------------------------------------------------
    subroutine SetFactor(factor)
      call usrget('XFAC', xfac0)
      call usrget('YFAC', yfac0)
      call usrset('XFAC', factor)
      call usrset('YFAC', factor)
    end subroutine

    subroutine ResetFactor
      call uspset('XFAC', xfac0)
      call uspset('YFAC', yfac0)
    end subroutine

    subroutine SetOffset(offset)
      call usrget('XOFF', xoff0)
      call usrget('YOFF', yoff0)
      call usrset('XOFF', offset)
      call usrset('YOFF', offset)
    end subroutine

    subroutine SetTitle(title)
      character(len=*) :: title
      call uscget('CXTTL', xttl0)
      call uscget('CYTTL', yttl0)
      call uscset('CXTTL', title)
      call uscset('CYTTL', title)
    end subroutine

    subroutine SetUnit(unit)
      character(len=*) :: unit
      call uscget('CXUNIT', xuni0)
      call uscget('CYUNIT', yuni0)
      call uscset('CXUNIT', unit)
      call uscset('CYUNIT', unit)
    end subroutine

    subroutine ResetOffset
      call uspset('XOFF', xoff0)
      call uspset('YOFF', yoff0)
    end subroutine

    subroutine SetSection(section)
      call uzrget('UXUSER', xsec0)
      call uzrget('UYUSER', ysec0)
      call uzrset('UXUSER', section)
      call uzrset('UYUSER', section)
    end subroutine

    subroutine ResetSection
      call uzpset('UXUSER', xsec0)
      call uzpset('UYUSER', ysec0)
    end subroutine

    subroutine ResetTitle
      call uscset('CXTTL', xttl0)
      call uscset('CYTTL', yttl0)
    end subroutine

    subroutine ResetUnit
      call uscset('CXUNIT', xuni0)
      call uscset('CYUNIT', yuni0)
    end subroutine
!-------------------------------------------------------------------

    subroutine DclScalingPoint(x, y)
      real, dimension(:), intent(in), optional :: x, y

      call prcopn('DclScalingPoint')
      call glrget('rundef', rundef)

      if(present(x) .and. present(y)) then
        nx = size(x)
        ny = size(y)
        if(nx.ne.ny) call msgdmp('M', 'DclScalingPoint', 'Length of x and y don''t match.')
        n = min(nx, ny)
        call usspnt(n, x, y)
      else if(present(x)) then
        n = size(x)
        call usspnt(n, x, (/rundef/))
      else if(present(y)) then
        n = size(y)
        call usspnt(n, (/rundef/), y)
      end if
      
      call prccls('DclScalingPoint')
    end subroutine
!----------------------------------------------------
    subroutine DclSetTitle(xtitle, ytitle, xunit, yunit)
      character(len=*), intent(in) :: xtitle, ytitle, xunit,  yunit
      optional                     :: xtitle, ytitle, xunit,  yunit
 
      call prcopn('DclSetTitle')

      if(present(xtitle)) call uscset('cxttl' , xtitle)
      if(present(ytitle)) call uscset('cyttl' , ytitle)
      if(present(xunit )) call uscset('cxunit', xunit)
      if(present(yunit )) call uscset('cyunit', yunit)

      call prccls('DclSetTitle')
    end subroutine
!----------------------------------------------------
    subroutine DclFitScalingParm
      call prcopn('DclFitScalingParm')
      call uspfit
      call prccls('DclFitScalingParm')
    end subroutine
!----------------------------------------------------
    subroutine DclDrawScaledAxis(side,section)
      character(len=*), intent(in), optional :: side
      real, optional :: section

      call sgoopn('DclDrawScaledAxis', ' ')
      if(present(section)) call SetSection(section)

      if(present(side)) then; call usaxsc(side)
                        else; call usdaxs
      end if

      if(present(section)) call ResetSection
      call sgocls('DclDrawScaledAxis')
    end subroutine
!----------------------------------------------------
    subroutine DclDrawScaledGraph(x, y, type, index)
      real,    intent(in), dimension(:) :: x, y
      integer, intent(in), optional     :: type,  index
      integer                           :: type0, index0

      call sgoopn('DclDrawScaledGraph', ' ')
      call glrget('rundef', rundef)

      if(present(type)) then;   type0 = type
                        else;   call sgqplt(type0)
      end if
        
      if(present(index)) then;  index0 = index
                         else;  call sgqpli(index0)
      end if

      nx = size(x)
      ny = size(y)
      if(nx.ne.ny) call msgdmp('M', 'DclScalingPoint', 'Length of x and y don''t match.')
      n = min(nx, ny)

      call usspnt(n, x, y)
      call uspfit
      call grstrf
      call usdaxs
      call sgplzu(n, x, y, type0, index0)
      call sgocls('DclDrawScaledGraph')

    end subroutine
!----------------------------------
!   UXYZPACK 座標軸
!---------------------------------- 目盛とラベルの間隔を指定して座標軸を描く
    subroutine DclDrawAxis(side,dlabel,dtick, &
                         & title,unit,factor,offset,section) 
      character(len=*), intent(in) :: side !座標軸を描く場所
      real, intent(in) :: dlabel, dtick    !目盛およびラベルの間隔
      character(len=*), intent(in), optional :: title, unit
      real, intent(in), optional :: factor,offset,section

      call sgoopn('DclDrawAxis', ' ')

      if(present(factor))  call SetFactor(factor)
      if(present(offset))  call SetOffset(offset)
      if(present(section)) call SetSection(section)
      if(present(title))   call SetTitle(title)
      if(present(unit))    call SetUnit(unit)

      call usaxdv(side,dtick,dlabel)

      if(present(factor))  call ResetFactor
      if(present(offset))  call ResetOffset
      if(present(section)) call ResetSection
      if(present(title))   call ResetTitle
      if(present(unit))    call ResetUnit

      call sgocls('DclDrawAxis')

    end subroutine
!---------------------------------- 目盛とラベルの場所を指定して座標軸を描く．
    subroutine DclDrawAxisSpecify(side,label_pos,tick_pos,label, &
                                & title, unit, factor, offset, section)
      character(len=*), intent(in) :: side       !座標軸を描く場所
      real, intent(in), dimension(:) :: label_pos       !大きめの目盛およびラベルの場所
      real, intent(in), dimension(:), optional :: tick_pos      !小さめの目盛の場所
      character(len=*), intent(in), dimension(:), optional :: label !ラベル
      character(len=*), intent(in), optional :: title, unit
      real, intent(in), optional :: factor, offset, section
      real, dimension(1) :: dummy      !小さめの目盛の場所


      call sgoopn('DclDrawAxisSpecify', ' ')

      if(present(factor))  call SetFactor(factor)
      if(present(offset))  call SetOffset(offset)
      if(present(section)) call SetSection(section)
      if(present(title))   call SetTitle(title)
      if(present(unit))    call SetUnit(unit)

      if (present(label)) then
        if(present(tick_pos)) then
          call usaxlb(side,tick_pos,size(tick_pos),label_pos,label,len(label(1)),size(label_pos))
        else
          call usaxlb(side, dummy, 0,label_pos,label,len(label(1)),size(label_pos))
        end if
      else
        if(present(tick_pos)) then
          call usaxnm(side,tick_pos,size(tick_pos),label_pos,size(label_pos))
        else
          call usaxnm(side, dummy,0,label_pos,size(label_pos))
        end if
      end if

      if(present(factor))  call ResetFactor
      if(present(offset))  call ResetOffset
      if(present(section)) call ResetSection
      if(present(title))   call ResetTitle
      if(present(unit))    call ResetUnit

      call sgocls('DclDrawAxisSpecify')

    end subroutine
!---------------------------------- LOG 座標軸を描く．
    subroutine DclDrawAxisLog(side, nlabel, nticks, &
                            & title, unit, format, cformat, factor, section, label_pos)
      character(len=*), intent(in)  :: side       !座標軸を描く場所
      integer, intent(in)           :: nlabel, nticks
      integer, intent(in), optional :: format
      character(len=*), intent(in), optional :: cformat
      character(len=*), intent(in), optional :: title, unit
      real,    intent(in), optional :: factor, section
      real,    intent(in), dimension(:), optional :: label_pos
      real, dimension(9) :: xlb, ylb

      call sgoopn('DclDrawAxisLog', ' ')

      if(present(factor))  call SetFactor(factor)
      if(present(section)) call SetSection(section)
      if(present(title))   call SetTitle(title)
      if(present(unit))    call SetUnit(unit)

      if(present(format))  then
        call uliget('IXTYPE', ix0)
        call uliget('IYTYPE', iy0)
        call uliset('IXTYPE', format)
        call uliset('IYTYPE', format)
      end if

      if(present(cformat))  then
        call ulxsfm(cformat)
        call ulxsfm(cformat)
      endif

      if(present(label_pos)) then
        call ulqxbl (xlb, 9 )
        call ulqybl (ylb, 9 )
        call ulsxbl (label_pos, size(label_pos) )
        call ulsybl (label_pos, size(label_pos) )
      end if

      call usaxlg(side,nlabel,nticks)

      if(present(factor))  call ResetFactor
      if(present(section)) call ResetSection
      if(present(title))   call ResetTitle
      if(present(unit))    call ResetUnit

      if(present(format))  then
        call uliset('IXTYPE', ix0)
        call uliset('IYTYPE', iy0)
      end if

      if(present(label_pos)) then
        call ulsxbl (xlb, 9 )
        call ulsybl (ylb, 9 )
      end if

      call sgocls('DclDrawAxisLog')

    end subroutine
!----------------------------------------
!   日付座標軸
!----------------------------------------
    subroutine DclDrawAxisCalendar (side,first_day, title, unit, type,nd) !日・月・年に関する座標軸を描く．
      character(len=*),  intent(in) :: side       !座標軸を書く場所を指定する
      type(dcl_date),    intent(in) :: first_day   !ucで0に相当する場所の日付を指定する
      character(len=*), intent(in), optional :: title, unit
      character(len=*),  intent(in), optional :: type        !年、月、日を YMD で指定する
      integer, optional, intent(in) :: nd          !作画する日数を指定する
      character(len=8)              :: type0

      call sgoopn('DclDrawAxisCalendar', ' ')

      jd = first_day%year*10000 + first_day%month*100 + first_day%day

      if(present(title))   call SetTitle(title)
      if(present(unit))    call SetUnit(unit)

      if(present(nd)) then; nd0 = nd
                      else; nd0 = 0
      end if

      if(present(type)) then; type0 = type
                        else; type0 = 'DMY'
      end if

      call usaxcl(side,jd,type0, nd0) 

      if(present(title))   call ResetTitle
      if(present(unit))    call ResetUnit

      call sgocls('DclDrawAxisCalendar')
    end subroutine
      
!----------------------------------
!   UXYZPACK 座標軸要素
!---------------------------------- タイトルを描く．
    subroutine DclDrawTitle(side,title,position,sw)
      character(len=*), intent(in) :: side     !座標軸を描く場所を指定する
      character(len=*), intent(in) :: title    !描くタイトル
      real,   optional, intent(in) :: position !位置:-1から+1の間の実数値
      integer,optional, intent(in) :: sw

      call sgoopn('DclDrawTitle', ' ')

      if(present(sw))       then;  isw=sw 
                            else;  isw=1
      end if

      if(present(position)) then;  pos=position 
                            else;  pos=0.
      end if

      call uspttl(side, isw, title, pos) 
      call sgocls('DclDrawTitle')
    end subroutine
!---------------------------------- 軸を示す線分を描く．
    subroutine DclDrawAxisLine(side,sw)
      character(len=*),  intent(in) :: side   !座標軸を描く場所を指定する
      integer, optional, intent(in) :: sw     !描く軸の属性を指定する

      call sgoopn('DclDrawAxisLine', ' ')

      if(present(sw)) then;  isw=sw 
                      else;  isw=1
      end if

      call uspaxs(side,isw)
      call sgocls('DclDrawAxisLine')
    end subroutine
!---------------------------------- 目盛を描く．
    subroutine DclDrawTickmark(side, position, sw)
      character(len=*), intent(in)        :: side      !目盛を描く座標軸の場所
      integer,   intent(in), optional     :: sw        !描く目盛の属性
      real,      intent(in), dimension(:) :: position  !目盛を描く場所
      integer                             :: isw

      call sgoopn('DclDrawTickmark', ' ')

      if(present(sw)) then;  isw=sw 
                      else;  isw=1
      end if
      call uxptmk(side, isw, position, size(position)) 
      call sgocls('DclDrawTickmark')
    end subroutine
!---------------------------------- 文字列で指定したラベルを描く
    subroutine DclDrawAxisLabel(side, position, label, sw)
      character(len=*), intent(in)               :: side     !ラベルを描く座標軸の場所
      real,             intent(in), dimension(:) :: position !ラベルを描く場所
      character(len=*), intent(in), dimension(:) :: label    !ラベル
      integer,          intent(in)               :: sw       !ラベルの属性
      optional :: label, sw

      call sgoopn('DclDrawAxisLabel', ' ')

      if(present(sw)) then;  isw=sw 
                      else;  isw=1
      end if

      if(present(label)) then
        call usplbl(side, isw, position, label, len(label(1)),size(position)) 
      else
        call uspnum(side, isw, position,size(position))
      end if 
      call sgocls('DclDrawAxisLabel')
    end subroutine
!---------------------------------- 軸をずらす。
    subroutine DclShiftAxis(side)
      character(len=*), intent(in) :: side

      call prcopn('DclShifAxis')
      call ussaxs(side)
      call prccls('DclShifAxis')
    end subroutine

end module
