# $Id$
#
# Copyright (C) 2009 Greg Landrum
#  All Rights Reserved
#
from __future__ import print_function
from rdkit.six.moves import cPickle
from rdkit.six import iterkeys
from rdkit import DataStructs,Chem
from rdkit import Chem

similarityMethods={'RDK':DataStructs.ExplicitBitVect,
                   'AtomPairs':DataStructs.IntSparseIntVect,
                   'TopologicalTorsions':DataStructs.LongSparseIntVect,
                   'Pharm2D':DataStructs.SparseBitVect,
                   'Gobbi2D':DataStructs.SparseBitVect,
                   'Morgan':DataStructs.UIntSparseIntVect
                   }
supportedSimilarityMethods=list(iterkeys(similarityMethods))


class LayeredOptions:
  loadLayerFlags=0xFFFFFFFF
  searchLayerFlags=0x7
  minPath=1
  maxPath=6
  fpSize=1024
  wordSize=32
  nWords=fpSize//wordSize
  @staticmethod
  def GetFingerprint(mol,query=True):
    if query:
      flags=LayeredOptions.searchLayerFlags
    else:
      flags=LayeredOptions.loadLayerFlags
    return Chem.LayeredFingerprint(mol,layerFlags=flags,
                                   minPath=LayeredOptions.minPath,maxPath=LayeredOptions.maxPath,
                                   fpSize=LayeredOptions.fpSize)
  @staticmethod
  def GetWords(mol,query=True):
    txt = LayeredOptions.GetFingerprint(mol,query=query).ToBitString()
    words = [int(txt[x:x+32],2) for x in range(0,len(txt),32)]
    return  words

  @staticmethod
  def GetQueryText(mol,query=True):
    words = LayeredOptions.GetWords(mol,query=query)
    colqs = []
    for idx,word in enumerate(words):
      if not word:
        continue
      idx = idx+1
      colqs.append('%(word)d&Col_%(idx)d=%(word)d'%locals())
    return  ' and '.join(colqs)



def BuildSigFactory(options=None,fdefFile=None,
                    bins=[(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,100)],
                    skipFeats=('LumpedHydrophobe','ZnBinder')):
  if options:
    fdefFile = options.fdefFile
  if not fdefFile:
    raise ValueError('bad fdef file')
  from rdkit.Chem import ChemicalFeatures
  from rdkit.Chem.Pharm2D import SigFactory
  featFactory = ChemicalFeatures.BuildFeatureFactory(fdefFile)
  sigFactory = SigFactory.SigFactory(featFactory,
                                     skipFeats=skipFeats,
                                     trianglePruneBins=False)
  sigFactory.SetBins(bins)
  return sigFactory

def BuildAtomPairFP(mol):
  from rdkit.Chem.AtomPairs import Pairs
  fp=Pairs.GetAtomPairFingerprintAsIntVect(mol)
  fp._sumCache = fp.GetTotalVal()
  return fp
def BuildTorsionsFP(mol):
  from rdkit.Chem.AtomPairs import Torsions
  fp=Torsions.GetTopologicalTorsionFingerprintAsIntVect(mol)
  fp._sumCache = fp.GetTotalVal()
  return fp
def BuildRDKitFP(mol):
  fp=Chem.RDKFingerprint(mol,nBitsPerHash=1)
  return fp
def BuildPharm2DFP(mol):
  global sigFactory
  from rdkit.Chem.Pharm2D import Generate
  try:
    fp=Generate.Gen2DFingerprint(mol,sigFactory)
  except IndexError:
    print('FAIL:',Chem.MolToSmiles(mol,True))
    raise
  return fp
def BuildMorganFP(mol):
  from rdkit.Chem import rdMolDescriptors
  fp = rdMolDescriptors.GetMorganFingerprint(mol,2)
  fp._sumCache = fp.GetTotalVal()
  return fp

def DepickleFP(pkl,similarityMethod):
    if not isinstance(pkl,(bytes,str)):
      pkl = str(pkl)
    try:
        klass=similarityMethods[similarityMethod]
        fp = klass(pkl)
    except:
        import traceback
        traceback.print_exc()
        fp = cPickle.loads(pkl)
    return fp
