
const
  TextTop=25;
  TextLeft=6;
  TextWidth=120;
  TextHeight=18;
  TextBottom=8;
  TextColor=$C19D82;
  TextSize=9;
  
var
  ShowDays:integer;
  lbls:TStrings;
  CurrentTop:integer;

procedure NewLabel(aCaption:string; aHint:string);
var
  lbl:TxspLabel;
begin
	lbl:=TxspLabel.Create(Widget);
  with lbl do
  begin
    parent:=Widget;
    caption:=aCaption;
    hint:=aHint;
    left:=TextLeft;
    top:=CurrentTop;
    width:=TextWidth;
    height:=16;
    FontStyle.Font.Color:=TextColor;
    FontStyle.Font.Size:=TextSize;
    CurrentTop:=CurrentTop+TextHeight;
  end;
  SetAllowMoveWidget(lbl);
 	lbls.AddObject(aCaption,lbl);
end;

function GetShowHoliday(lstHoliday:TStrings):string;
var
  i:integer;
  bShowSolar,bShowLunar,bShowOther:boolean;
  lst:TStrings;
begin
  result:='';
  if lstHoliday.count<=0 then exit;
  bShowSolar:=GetSettingBool('ShowSolar',true);
  bShowLunar:=GetSettingBool('ShowLunar',true);
  bShowOther:=GetSettingBool('ShowOther',true);
  lst := TStringList.create;
  try
	  for i:=0 to lstHoliday.count-1 do
	  begin
      if (i<=35) and bShowLunar then//农历节日
        lst.Add(lstHoliday.strings[i])
      else if bShowSolar and ((37<=i) and (i<=60)) then //阳历节日
        lst.Add(lstHoliday.strings[i])
      else if bShowOther and (i>=62) then  //其它节日
        lst.Add(lstHoliday.strings[i]);
    end;
    result := lst.text;
  finally
    lst.free;
  end;
end;

//指定日期是这个月的第几个星期几
function WeeksInMonth(AValue:TDate):Word;
var
  I: Integer;
  y,m,d:word;
  WeekNum,Weeks:integer;
  dt:TDateTime;
begin
  WeekNum:=DayOfTheWeek(dt);
  Weeks:=0;
  dt:=0;
  DecodeDate(AValue,y,m,d);
  for I := 1 to d do    
  begin
    dt:=EncodeDate(y,m,i);
    if DayOfTheWeek(dt)=WeekNum then inc(Weeks);
  end;   
  result:=Weeks; 
end;

procedure ParseHoliday;
var
  i,j:integer;
  lstHoliday,lstLunar,lstSolar,lst:TStrings;
  dt:TDate;
  iDay,iStartYear:integer;
  y,m,d:word;
  sDay,sCaption,sHint:string;
  
  lbl:TxspLabel;
begin
  CurrentTop:=TextTop;
  if lbls.count>0 then
  begin
    for i:=0 to lbls.count-1 do
    begin
      lbl:=TxspLabel(lbls.Objects[i]);
      lbls.Objects[i]:=nil;
      lbl.free;
    end;
    lbls.Clear;
  end;

  lstHoliday:=TStringList.Create;
  lstLunar:=TStringList.Create;
  lstSolar:=TStringList.Create;
  lst:=TStringList.Create;
  BeginUpdate;
  try
    lstHoliday.LoadFromFile(AppPath+'Data\Holiday.dat');
    lstHoliday.text :=UTF8Decode(lstHoliday.text);
    lstHoliday.text:=GetShowHoliday(lstHoliday);
    if lstHoliday.count>0 then
      for i:=0 to lstHoliday.count-1 do
      begin
        if pos('isLunar=1',lstHoliday.strings[i])>0 then
          lstLunar.Add(lstHoliday.strings[i])
        else
          lstSolar.Add(lstHoliday.strings[i]);
      end;
    
    dt:=now;
    iDay:=0;
    while iDay<ShowDays do
    begin
      //--- solar ---
      DecodeDate(dt,y,m,d);
      sDay:=format('%d.%d',[m,d]);
      while lstSolar.IndexOfName(sDay)>0 do
      begin
        j:=lstSolar.IndexOfName(sDay);
        lst.text:=StrToStrings(lstSolar.ValueFromIndex[j],',');
        if trunc(dt)-trunc(now)=0 then
          sCaption:=format('[今天]%s',[lst.Values['Caption']])
        else
          sCaption:=format('[%d天]%s',[trunc(dt)-trunc(now),lst.Values['Caption']]);
        sHint:=format('节日：%s'#13#10'日期：%s',[lst.Values['Caption'],FormatDateTime('yyyy-mm-dd',dt)]);
        if (lst.IndexOfName('StartYear')>0) then
        try
          iStartYear:=StrToInt(lst.Values['StartYear']);
        except
          iStartYear:=0;
        end
        else iStartYear:=0;
        if (iStartYear>0) then sHint:=sHint+#13#10+format('开始年份：%d年',[iStartYear]);
        NewLabel(sCaption,sHint);
        inc(iDay);
        if iDay>=ShowDays then break;
        lstSolar.Delete(j);
      end;
      if iDay>=ShowDays then break;
      
      //--- lunar ---
      sDay:=DateToDateCnStr(dt,'m.d');
      while lstLunar.IndexOfName(sDay)>0 do
      begin
        j:=lstLunar.IndexOfName(sDay);
        lst.text:=StrToStrings(lstLunar.ValueFromIndex[j],',');
        if trunc(dt)-trunc(now)=0 then
          sCaption:=format('[今天]%s',[lst.Values['Caption']])
        else
          sCaption:=format('[%d天]*%s',[trunc(dt)-trunc(now),lst.Values['Caption']]);
        sHint:=format('节日：%s'#13#10'日期：%s'#13#10'农历：%s',[lst.Values['Caption'],FormatDateTime('yyyy-mm-dd',dt),DateToDatecnstr(dt,'mmmm月ddd')]);
        if (lst.IndexOfName('StartYear')>0) then
        try
          iStartYear:=StrToInt(lst.Values['StartYear']);
        except
          iStartYear:=0;
        end
        else iStartYear:=0;
        if (iStartYear>0) then sHint:=sHint+#13#10+format('开始年份：%d年',[iStartYear]);
        NewLabel(sCaption,sHint);
        inc(iDay);
        if iDay>=ShowDays then break;
        lstLunar.Delete(j);
      end;
      if iDay>=ShowDays then break;
      
      //--- Other ---
      //增加对 某月第几周第几个星期几 这种节日的支持
      sDay:=format('%d=Week=%d,Day=%d',[m,WeeksInMonth(dt),DayOfTheWeek(dt)]);
      Array_Week := ['一','二','三','四','五','六','天'];
      if lstSolar.count>0 then
        for i:=lstSolar.count-1 downto 0 do
        begin
          if pos(sDay,lstSolar.strings[i])>0 then
          begin
            lst.text:=StrToStrings(lstSolar.ValueFromIndex[i],',');
            if trunc(dt)-trunc(now)=0 then
              sCaption:=format('[今天]%s',[lst.Values['Caption']])
            else
              sCaption:=format('[%d天]%s',[trunc(dt)-trunc(now),lst.Values['Caption']]);
            sHint:=format('节日：%s'#13#10'日期：%s'#13#10'时间：%d月第%d个星期%s',
              [lst.Values['Caption'],FormatDateTime('yyyy-mm-dd',dt),m,WeeksInMonth(dt),Array_Week[DayOfTheWeek(dt)-1]]);
            if (lst.IndexOfName('StartYear')>0) then
            try
              iStartYear:=StrToInt(lst.Values['StartYear']);
            except
              iStartYear:=0;
            end
            else iStartYear:=0;
            if (iStartYear>0) then sHint:=sHint+#13#10+format('开始年份：%d年',[iStartYear]);
            NewLabel(sCaption,sHint);
            inc(iDay);
            if iDay>=ShowDays then break;
            lstSolar.Delete(i);
          end;
        end;
        
      dt:=dt+1;
    end;
  finally
    imgbg.height:=TextTop+lbls.count*TextHeight+TextBottom;
    //showmessage(lbls.count);
    Widget.height:=imgbg.height;
    EndUpdate;
    lst.free;
    lstSolar.free;
    lstLunar.free;
    lstHoliday.free;
  end;
end;

procedure nShowHolidayClick(Sender:TObject);
begin
  SetSettingBool('ShowLunar',nShowLunar.Checked);
  SetSettingBool('ShowSolar',nShowSolar.Checked);
  SetSettingBool('ShowOther',nShowOther.Checked);
  ParseHoliday;
end;

//--- Widget初始化事件，当打开Widget时会触发此事件 ---
procedure OnWidgetInit;
begin
  lbls:=TStringList.Create;
  ShowDays:=GetSettingInt('ShowDays',7);
  nShowLunar.Checked:=GetSettingBool('ShowLunar',true);
  nShowSolar.Checked:=GetSettingBool('ShowSolar',true);
  nShowOther.Checked:=GetSettingBool('ShowOther',true);
  ParseHoliday;
end;

//--- Widget关闭事件，当关闭Widget时会触发此事件 ---
procedure OnWidgetClose;
begin
  lbls.free;
end;

//--- Widget移入边栏事件，当Widget被移到边栏上时会触发此事件 ---
procedure OnWidgetDock;
begin
  Widget.Width:=136;
end;

//--- Widget移出边栏事件，当Widget被移出边栏时会触发此事件 ---
procedure OnWidgetUnDock;
begin
  Widget.Width:=142;
end;
