module Data.Vhd.Geometry where

import Data.Vhd.Types
import Data.Word

-- | Calculates disk geometry using the algorithm presented in
-- | the virtual hard disk image format specification (v 1.0).
diskGeometry :: Word64 -> DiskGeometry
diskGeometry totalSectors' =
    let (sectorsPerTrack, heads, cylindersTimesHeads) = calculate in
    let cylinders = cylindersTimesHeads `div` heads in
    DiskGeometry
        (fromIntegral cylinders)
        (fromIntegral heads)
        sectorsPerTrack
  where
        totalSectors = min totalSectors' (65535 * 16 * 255)
        calculate
            | totalSectors > 65536 * 16 * 63  = (255, 16, totalSectors `div` 255)
            | otherwise                       =
                let sectorsPerTrack = 17 in
                let cylindersTimesHeads = totalSectors `div` 17 in
                let heads = max 4 $ (cylindersTimesHeads + 1023) `div` 1024 in
                let (sectorsPerTrack', heads', cylindersTimesHeads') =
                        if cylindersTimesHeads >= heads * 1024 || heads > 16
                            then (31, 16, totalSectors `div` 31)
                            else (sectorsPerTrack, heads, cylindersTimesHeads) in
                if cylindersTimesHeads' >= heads' * 1024
                    then (63, 16, totalSectors `div` 63)
                    else (sectorsPerTrack', heads', cylindersTimesHeads')