unit CatalogCompressWin;

{$WARN UNIT_PLATFORM OFF}
{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  Windows, SysUtils, Forms, Classes, Controls, StdCtrls, Buttons, ComCtrls,
  _SimpleDialog;

{$WARN UNIT_PLATFORM OFF}
{$WARN SYMBOL_PLATFORM OFF}

type
  TCatalogInfo=record
    FileSize,DataSize:integer;
    Total,Enable,Disable:integer;
  end;

type
  TCatalogCompress = class(TForm)
    GroupBox2: TGroupBox;
    unFileSizeLbl: TLabel;
    unDataSizeLbl: TLabel;
    unTotalLbl: TLabel;
    unEnableLbl: TLabel;
    unDisableLbl: TLabel;
    CompFileSizeLbl: TLabel;
    CompDataSizeLbl: TLabel;
    CompTotalLbl: TLabel;
    CompEnableLbl: TLabel;
    CompDisableLbl: TLabel;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label7: TLabel;
    Label6: TLabel;
    CloseBtn: TBitBtn;
    CompressBtn: TBitBtn;
    DeleteBtn: TButton;
    ProgBar: TProgressBar;
    procedure CompressBtnClick(Sender: TObject);
    procedure DeleteBtnClick(Sender: TObject);
  private
    { Private 宣言 }
    IndexFilename,DataFilename:string;
    procedure SetunInfo(var CatalogInfo:TCatalogInfo);
    procedure SetCompInfo(var CatalogInfo:TCatalogInfo);
    procedure ClearInfo(var CatalogInfo:TCatalogInfo);
    procedure GetCatalogInfo(var CatalogInfo:TCatalogInfo);
  public
    { Public 宣言 }
    procedure Init(_IndexFilename,_DataFilename:string);
  end;

var
  CatalogCompress: TCatalogCompress;

implementation

uses MainWin,
     _MainFileCtl,_const, _MDXWin_const, _fsTools;

{$R *.dfm}

procedure TCatalogCompress.SetunInfo(var CatalogInfo:TCatalogInfo);
begin
  with CatalogInfo do begin
    unFileSizeLbl.Caption:=IntToStr(FileSize div 1024)+'kb';
    unDataSizeLbl.Caption:=IntToStr(DataSize div 1024)+'kb';
    unTotalLbl.Caption:=IntToStr(Total);
    unEnableLbl.Caption:=IntToStr(Enable);
    unDisableLbl.Caption:=IntToStr(Disable);
  end;
end;

procedure TCatalogCompress.SetCompInfo(var CatalogInfo:TCatalogInfo);
begin
  with CatalogInfo do begin
    CompFileSizeLbl.Caption:=IntToStr(FileSize div 1024)+'kb';
    CompDataSizeLbl.Caption:=IntToStr(DataSize div 1024)+'kb';
    CompTotalLbl.Caption:=IntToStr(Total);
    CompEnableLbl.Caption:=IntToStr(Enable);
    CompDisableLbl.Caption:=IntToStr(Disable);
  end;
end;

procedure TCatalogCompress.ClearInfo(var CatalogInfo:TCatalogInfo);
begin
  with CatalogInfo do begin
    FileSize:=0;
    DataSize:=0;
    Total:=0;
    Enable:=0;
    Disable:=0;
  end;
end;

procedure TCatalogCompress.Init(_IndexFilename,_DataFilename:string);
var
  CatalogInfo:TCatalogInfo;
  Idxfs,Datafs:TFileStream;
begin
  IndexFilename:=_IndexFilename;
  DataFilename:=_DataFilename;

  CompressBtn.Enabled:=True;
  DeleteBtn.Enabled:=True;
  CloseBtn.Enabled:=True;

  if (FileExists(IndexFilename)=False) or (FileExists(DataFilename)=False) then begin
    ShowMessage('MDXWin.exe','カタログファイルがありません。'+CRLF+'MDXOnlineのみ使用時はローカルカタログは作成されません。');
    CatalogCompress.Visible:=False;
    CompressBtn.Enabled:=False;
    DeleteBtn.Enabled:=False;
    exit;
    end else begin
    Idxfs:=TFileStream.Create(IndexFilename,fmOpenReadWrite or fmShareDenyWrite);
    if GetStreamMString(Idxfs)<>CatalogIndexHeadder then begin
      ShowMessage('MDXWin.exe','カタログインデックスヘッダが異常です');
      CatalogCompress.Visible:=False;
      CompressBtn.Enabled:=False;
      Idxfs.Free;
      exit;
      end else begin
      Idxfs.Free;
    end;

    Datafs:=TFileStream.Create(DataFilename,fmOpenReadWrite or fmShareDenyWrite);
    if GetStreamMString(Datafs)<>CatalogDataHeadder then begin
      ShowMessage('MDXWin.exe','カタログデータヘッダが異常です');
      CatalogCompress.Visible:=False;
      CompressBtn.Enabled:=False;
      Datafs.Free;
      exit;
      end else begin
      Datafs.Free;
    end;
  end;

  GetCatalogInfo(CatalogInfo);
  SetunInfo(CatalogInfo);

  if CatalogInfo.Disable=0 then begin
    ShowMessage('MDXWin.exe','最適化する必要はありません。');
    CatalogCompress.Visible:=False;
  end;

  ClearInfo(CatalogInfo);
  SetCompInfo(CatalogInfo);
end;

procedure TCatalogCompress.GetCatalogInfo(var CatalogInfo:TCatalogInfo);
var
  CatalogIndex:TCatalogIndex;
  Idxfs,Datafs:TFileStream;
  function CheckDataFile(CatalogInfo:TCatalogInfo):boolean;
  var
    Size:integer;
  begin
    Datafs.Position:=CatalogIndex.Segment;
    Size:=GetStreamDWord(Datafs);
    Datafs.Position:=integer(CatalogIndex.Segment)+Size;
    if GetStreamDWord(Datafs)=$00000000 then
      Result:=True
      else
      Result:=False;
  end;
begin
  ClearInfo(CatalogInfo);

  Idxfs:=TFileStream.Create(IndexFilename,fmOpenReadWrite or fmShareDenyWrite);
  GetStreamMString(Idxfs);
  CatalogInfo.FileSize:=Idxfs.Size;

  Datafs:=TFileStream.Create(DataFilename,fmOpenReadWrite or fmShareDenyWrite);
  GetStreamMString(Datafs);
  CatalogInfo.DataSize:=Datafs.Size;

  ProgBar.Max:=Idxfs.Size;
  ProgBar.Position:=0;
  with CatalogInfo do begin
    Total:=0;
    Enable:=0;
    Disable:=0;
    while Idxfs.Position<Idxfs.Size do begin
      inc(Total);
      if (Total mod 16)=0 then ProgBar.Position:=Idxfs.Position;
      with CatalogIndex do begin
        Offset:=Idxfs.Position;
        Serial:=GetStreamDWord(Idxfs);
        Segment:=GetStreamDWord(Idxfs);
        Path:=GetStreamMString(Idxfs);

        if (Path[1]='.') or (DirectoryExists(MainFileCtl.GetTruePathFromVirtualPath(Path))=False) then begin
          inc(Disable);
          end else begin
          if CheckDataFile(CatalogInfo)=False then begin
            inc(Disable);
            end else begin
            inc(Enable);
          end;
        end;
      end;
    end;
  end;
  ProgBar.Position:=0;

  Idxfs.Free;
  Datafs.Free;
end;

procedure TCatalogCompress.CompressBtnClick(Sender: TObject);
var
  Total:integer;
  CatalogInfo:TCatalogInfo;
  CatalogIndex:TCatalogIndex;
  SrcIndexFilename,SrcDataFilename:string;
  SrcIdxfs,SrcDatafs:TFileStream;
  DstIdxfs,DstDatafs:TFileStream;
  SrcDataSize:integer;
begin
  SrcIndexFilename:=ChangeFileExt(IndexFilename,'.idxbak');
  SrcDataFilename:=ChangeFileExt(DataFilename,'.datbak');
  if FileExists(SrcIndexFilename)=True then DeleteFile(SrcIndexFilename);
  if FileExists(SrcDataFilename)=True then DeleteFile(SrcDataFilename);
  RenameFile(IndexFilename,SrcIndexFilename);
  RenameFile(DataFilename,SrcDataFilename);

  SrcIdxfs:=TFileStream.Create(SrcIndexFilename,fmOpenRead or fmShareDenyWrite);
  SrcDatafs:=TFileStream.Create(SrcDataFilename,fmOpenRead or fmShareDenyWrite);
  GetStreamMString(SrcIdxfs);
  GetStreamMString(SrcDatafs);
  DstIdxfs:=TFileStream.Create(IndexFilename,fmCreate or fmShareDenyWrite);
  DstDatafs:=TFileStream.Create(DataFilename,fmCreate or fmShareDenyWrite);
  SetStreamMString(DstIdxfs,CatalogIndexHeadder);
  SetStreamMString(DstDatafs,CatalogDataHeadder);

  ProgBar.Max:=SrcIdxfs.Size;
  ProgBar.Position:=0;
  Total:=0;
  while SrcIdxfs.Position<SrcIdxfs.Size do begin
    inc(Total);
    if (Total mod 16)=0 then ProgBar.Position:=SrcIdxfs.Position;
    with CatalogIndex do begin
      Offset:=SrcIdxfs.Position;
      Serial:=GetStreamDWord(SrcIdxfs);
      Segment:=GetStreamDWord(SrcIdxfs);
      Path:=GetStreamMString(SrcIdxfs);

      if (Path[1]<>'.') and (DirectoryExists(MainFileCtl.GetTruePathFromVirtualPath(Path))=True) then begin
        SrcDatafs.Position:=Segment;
        SrcDataSize:=GetStreamDWord(SrcDatafs);
        if GetStreamMString(SrcDatafs)=Path then begin
          DstDatafs.Position:=DstDatafs.Size;
          SetStreamDWord(DstIdxfs,Serial);
          SetStreamDWord(DstIdxfs,DstDatafs.Position);
          SetStreamMString(DstIdxfs,Path);

          SetStreamDWord(DstDatafs,SrcDataSize);
          SetStreamMString(DstDatafs,Path);

          while (SrcDatafs.Position-Segment)<SrcDataSize do begin
            SetStreamMString(DstDatafs,GetStreamMString(SrcDatafs));
            SetStreamMString(DstDatafs,GetStreamMString(SrcDatafs));
          end;
          SetStreamDWord(DstDatafs,$00000000);
        end;
      end;
    end;
  end;
  ProgBar.Position:=0;

  SrcIdxfs.Free;
  SrcDatafs.Free;
  DstIdxfs.Free;
  DstDatafs.Free;

  GetCatalogInfo(CatalogInfo);
  SetCompInfo(CatalogInfo);
  ShowMessage('MDXWin.exe','カタログパッケージの最適化が終了しました。');
end;

procedure TCatalogCompress.DeleteBtnClick(Sender: TObject);
var
  SrcIndexFilename,SrcDataFilename:string;
begin
  if MessageDlgisOK('MDXWin.exe','カタログパッケージを削除しますか？'+#13+#10+'この処理では、タイトルキャッシュを初期化します。',MB_Warrning)=True then begin
    SrcIndexFilename:=ChangeFileExt(IndexFilename,'.idxbak');
    SrcDataFilename:=ChangeFileExt(DataFilename,'.datbak');
    if FileExists(IndexFilename)=True then begin
      if FileExists(SrcIndexFilename)=True then DeleteFile(SrcIndexFilename);
      RenameFile(IndexFilename,SrcIndexFilename);
    end;
    if FileExists(DataFilename)=True then begin
      if FileExists(SrcDataFilename)=True then DeleteFile(SrcDataFilename);
      RenameFile(DataFilename,SrcDataFilename);
    end;
    ShowMessage('MDXWin.exe','バックアップの作成と、カタログパッケージの削除が終了しました。');
    ModalResult:=mrOK;
  end;
end;

end.
