@echo off
setlocal
rem ============================================================================
rem  Hasaki - Bo cai in tem ma vach (barcode.hasaki.vn)  -  v1.0 2026-08-06
rem  Tu dong lam (can quyen Administrator - bam Yes khi Windows hoi):
rem    1. Tao 2 kho giay chuan:  Hasaki 88x10  (88.0 x 10.0 mm - cuon tem 21x10)
rem                              Hasaki 105x22 (105.0 x 22.0 mm - cuon tem 35x22)
rem    2. Tat "Dau trang va chan trang" khi in cho Chrome + Edge (chinh sach may)
rem    3. Kiem tra da co driver may in tem chua (TSC / Honeywell)
rem  KHONG dong cham stock/kho giay cu da tao truoc do.
rem  Go bo: xoa 2 form trong Print server properties > Forms; xoa gia tri
rem         PrintHeaderFooter trong HKLM\SOFTWARE\Policies\{Google\Chrome,Microsoft\Edge}
rem  Log: %TEMP%\hasaki-barcode-setup.log
rem ============================================================================

net session >nul 2>&1
if %errorlevel% neq 0 (
  echo Dang xin quyen Administrator... Bam Yes o hop thoai ke tiep.
  powershell -NoProfile -Command "Start-Process -FilePath '%~f0' -Verb RunAs"
  exit /b
)

echo.
echo === Hasaki - Cai dat in tem ma vach ===
echo.
powershell -NoProfile -ExecutionPolicy Bypass -Command "$s=[IO.File]::ReadAllText('%~f0'); $m='###'+'PSBEGIN'+'###'; $i=$s.LastIndexOf($m); Invoke-Expression $s.Substring($i+$m.Length)"
echo.
pause
exit /b

###PSBEGIN###
$ErrorActionPreference = 'Stop'
try { Start-Transcript -Path (Join-Path $env:TEMP 'hasaki-barcode-setup.log') -Force | Out-Null } catch {}

Write-Host '--- Buoc 1/3: tao kho giay chuan ---'
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
public class HskForm {
  [StructLayout(LayoutKind.Sequential)] public struct SIZEL { public int cx; public int cy; }
  [StructLayout(LayoutKind.Sequential)] public struct RECTL { public int left; public int top; public int right; public int bottom; }
  [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
  public struct FORM_INFO_1 { public uint Flags; public string pName; public SIZEL Size; public RECTL ImageableArea; }
  [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
  public struct PRINTER_DEFAULTS { public string pDatatype; public IntPtr pDevMode; public uint DesiredAccess; }
  [DllImport("winspool.drv", SetLastError=true, CharSet=CharSet.Unicode)]
  public static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, ref PRINTER_DEFAULTS pDefault);
  [DllImport("winspool.drv", SetLastError=true)]
  public static extern bool ClosePrinter(IntPtr hPrinter);
  [DllImport("winspool.drv", SetLastError=true, CharSet=CharSet.Unicode)]
  public static extern bool AddForm(IntPtr hPrinter, uint Level, ref FORM_INFO_1 pForm);
  [DllImport("winspool.drv", SetLastError=true, CharSet=CharSet.Unicode)]
  public static extern bool DeleteForm(IntPtr hPrinter, string pFormName);
}
'@

$printers = @(Get-Printer | Where-Object { $_.Type -eq 'Local' })
if ($printers.Count -eq 0) { $printers = @(Get-Printer) }
if ($printers.Count -eq 0) { throw 'May nay chua co bat ky may in nao - cai driver may in truoc roi chay lai file nay.' }
$target = $printers | Where-Object { $_.Name -match 'TSC|PE200|PC42|Honeywell' } | Select-Object -First 1
$handleOn = if ($target) { $target.Name } else { $printers[0].Name }

$pd = New-Object HskForm+PRINTER_DEFAULTS
$pd.pDatatype = $null; $pd.pDevMode = [IntPtr]::Zero
$pd.DesiredAccess = 0x000F000C   # PRINTER_ALL_ACCESS
$h = [IntPtr]::Zero
if (-not [HskForm]::OpenPrinter($handleOn, [ref]$h, [ref]$pd)) {
  throw "Khong mo duoc may in '$handleOn' (ma loi $([Runtime.InteropServices.Marshal]::GetLastWin32Error()))"
}
try {
  foreach ($spec in @(@('Hasaki 88x10',88,10), @('Hasaki 105x22',105,22))) {
    $name = $spec[0]; $wmm = $spec[1]; $hmm = $spec[2]
    [HskForm]::DeleteForm($h, $name) | Out-Null   # xoa ban cu neu co (chay lai an toan)
    $f = New-Object HskForm+FORM_INFO_1
    $f.Flags = 0                                   # FORM_USER
    $f.pName = $name
    $f.Size = New-Object HskForm+SIZEL
    $f.Size.cx = $wmm * 1000; $f.Size.cy = $hmm * 1000        # don vi 1/1000 mm
    $f.ImageableArea = New-Object HskForm+RECTL
    $f.ImageableArea.left = 0; $f.ImageableArea.top = 0
    $f.ImageableArea.right = $wmm * 1000; $f.ImageableArea.bottom = $hmm * 1000
    if (-not [HskForm]::AddForm($h, 1, [ref]$f)) {
      throw "Tao kho giay '$name' that bai (ma loi $([Runtime.InteropServices.Marshal]::GetLastWin32Error()))"
    }
    Write-Host ("  [OK] Kho giay '{0}' = {1} x {2} mm" -f $name, $wmm, $hmm)
  }
} finally { [HskForm]::ClosePrinter($h) | Out-Null }

Write-Host '--- Buoc 2/3: tat Dau trang va chan trang (Chrome + Edge) ---'
foreach ($root in 'HKLM:\SOFTWARE\Policies\Google\Chrome', 'HKLM:\SOFTWARE\Policies\Microsoft\Edge') {
  New-Item -Path $root -Force | Out-Null
  New-ItemProperty -Path $root -Name 'PrintHeaderFooter' -PropertyType DWord -Value 0 -Force | Out-Null
}
Write-Host '  [OK] Da tat qua chinh sach may (nguoi dung khoi phai nho bo tich)'

Write-Host '--- Buoc 3/3: kiem tra driver may in tem ---'
if ($target) {
  Write-Host ("  [OK] Da co may in tem: {0}" -f $target.Name)
} else {
  Write-Host '  [CHU Y] Chua thay may in TSC/Honeywell tren may nay.'
  Write-Host '          Neu chua cai driver: cai driver theo dia/trang chu hang,'
  Write-Host '          cam may in vao roi chay lai file nay (khong bat buoc -'
  Write-Host '          kho giay da tao san, dung duoc ngay khi co may in).'
}

Write-Host ''
Write-Host '=== XONG! Cach in: mo Chrome vao  barcode.hasaki.vn  go ma -> Enter ==='
Write-Host 'Lan dau tren may nay, trong hop thoai in chon 1 lan (Chrome se tu nho):'
Write-Host '  - May in dich  : may in tem (TSC PE200 / Honeywell PC42t plus)'
Write-Host '  - Kho giay     : Hasaki 88x10 (cuon tem 21x10)  hoac  Hasaki 105x22 (cuon 35x22)'
Write-Host '  - Le           : Khong co (None)'
Write-Host '  - Ty le        : Tuy chinh -> 100'
Write-Host 'Xem truoc phai THAY ma vach roi moi bam In. Chi tiet: barcode.hasaki.vn/huong-dan.pdf'
try { Stop-Transcript | Out-Null } catch {}
