# -*- coding: utf-8 -*-
# [SKRIP I3.3] Domain nilai yang tersimpan DI DALAM GeoPackage (daftar Kondisi dan rentang Tinggi_Phn),
# lalu membuktikan dua hal: QGIS ikut membacanya, dan penulisan lewat program tidak otomatis ditolak.
# Penulis: Badar Mubarok Yogaswara
# Jalankan setelah skrip I3.2, dengan python-qgis.bat (butuh modul osgeo.ogr). Bekerja pada berkas Survei_KPH.gpkg.
from osgeo import ogr, gdal
from qgis.core import QgsVectorLayer, QgsVectorLayerUtils

gdal.UseExceptions()
ogr.UseExceptions()
GPKG = r"D:/KPH_Contoh/Survei_KPH.gpkg"

ds = ogr.Open(GPKG, 1)
lyr = ds.GetLayerByName("Titik_Survei")

# 1. Buat dua domain pada tingkat berkas
ds.AddFieldDomain(ogr.CreateCodedFieldDomain(
    "Kondisi_Pohon", "Kondisi pohon hasil survei", ogr.OFTString, ogr.OFSTNone,
    {"Sehat": "Sehat", "Terserang Hama": "Terserang Hama", "Tebangan Liar": "Tebangan Liar"}))
ds.AddFieldDomain(ogr.CreateRangeFieldDomain(
    "Tinggi_Pohon", "Tinggi pohon 0 sampai 60 m", ogr.OFTReal, ogr.OFSTNone, 0.0, True, 60.0, True))

# 2. Pasang domain ke kolomnya
for kolom, domain in [("Kondisi", "Kondisi_Pohon"), ("Tinggi_Phn", "Tinggi_Pohon")]:
    i = lyr.GetLayerDefn().GetFieldIndex(kolom)
    lama = lyr.GetLayerDefn().GetFieldDefn(i)
    fd = ogr.FieldDefn(lama.GetName(), lama.GetType())          # salinan definisi kolom; yang lama tidak boleh diubah langsung
    fd.SetDomainName(domain)
    lyr.AlterFieldDefn(i, fd, ogr.ALTER_DOMAIN_FLAG)
print("Domain di berkas:", ds.GetFieldDomainNames())
ds = None

# 3. QGIS membaca domain itu sebagai widget formulir
uji = QgsVectorLayer(GPKG + "|layername=Titik_Survei", "uji", "ogr")
for kolom in ["Kondisi", "Tinggi_Phn"]:
    w = uji.editorWidgetSetup(uji.fields().indexOf(kolom))
    print("Widget %-11s: %s" % (kolom, w.type()))

# 4. Domain bukan gembok: nilai di luar daftar tetap bisa tertulis lewat program
ds = ogr.Open(GPKG, 1)
lyr = ds.GetLayerByName("Titik_Survei")
f = ogr.Feature(lyr.GetLayerDefn())
f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(312100 9996100)"))
f.SetField("ID_Survei", "UJI-DOMAIN")
f.SetField("Kondisi", "ngawur")
f.SetField("Tinggi_Phn", 250.0)
lyr.CreateFeature(f)
print("Nilai 'ngawur' dan tinggi 250 m: tertulis tanpa ditolak")
ds.ExecuteSQL("DELETE FROM Titik_Survei WHERE ID_Survei = 'UJI-DOMAIN'")       # bersihkan baris uji
ds = None
