{-# LANGUAGE RecordWildCards #-}

-- | Import data from a Turner table structure. Those can be imported using the
-- Turner.Import module.

module Biobase.Vienna.Import.Turner
  ( fromTurner
  ) where

import Control.Arrow
import Data.Tuple.All
import qualified Data.Map as M

import Biobase.Turner.Tables
import Biobase.Turner
import Data.PrimitiveArray
import Biobase.Constants
import Biobase.RNA

import Biobase.Vienna
-- | Convert from Turner keys to Vienna keys and all values from Double to Int

fromTurner :: TurnerTables -> ViennaIntTables
fromTurner Turner2004{..} = Turner2004
  { stack = convert pp stack
  , dangle3 = convert pb dangle3
  , dangle5 = convert pb dangle5
  , hairpinL = amap f2i hairpinL
  , hairpinMM = convert pbb hairpinMM
  , hairpinLookup = M.map f2i hairpinLookup
  , bulgeL = amap f2i bulgeL
  , iloop1x1 = convert uu iloop1x1
  , iloop1x2 = convert uu iloop1x2
  , iloop2x2 = convert uu iloop2x2
  , iloopMM = convert pbb iloopMM
  , iloop2x3MM = convert pbb iloop2x3MM
  , iloop1xnMM = convert pbb iloop1xnMM
  , iloopL = amap f2i iloopL
  , multiMM = convert pbb multiMM
  , ninio = f2i ninio
  , maxNinio = f2i maxNinio
  , multiOffset = f2i multiOffset
  , multiNuc = f2i multiNuc
  , multiHelix = f2i multiHelix
  , extMM = convert pbb extMM
  , largeLoop = largeLoop * 100 -- scale to decacals
  , termAU = f2i termAU
  , intermolecularInit = f2i intermolecularInit
  }



-- * Helper functions.

-- | Vienna values are Int's that have 2-digit precision.

f2i :: Double -> Int
f2i d = round $ d * 100


-- | Deep breath ;-)

pp = both tuple2Vienna
pb = first tuple2Vienna
pbb t = upd1 (tuple2Vienna $ sel1 t) t
uu t = upd2 (tuple2Vienna $ sel2 t) $ upd1 (tuple2Vienna $ sel1 t) t
both f = first f . second f

-- | Do the conversion, both on keys and values.

convert fk = fromAssocs minBound maxBound eInf . map (first fk . second f2i) . assocs