class PDBReader extends DefaultChemObjectReader {

    @Override
    public <T extends IChemObject> T read(T oObj) throws CDKException {
        if (oObj instanceof IChemFile) {
            return (T) readChemFile((IChemFile) oObj);
        } else {
            throw new CDKException("Only supported is reading of ChemFile objects.");
        }
    }

}

class PDBReaderTest extends DefaultChemObjectReader {

    @Test
    public void test1D66() throws Exception {

        String filename = "data/pdb/1D66.pdb";
        InputStream ins = this.getClass().getClassLoader().getResourceAsStream(filename);

        ISimpleChemObjectReader reader = new PDBReader(ins);
        Assert.assertNotNull(reader);

        IChemFile chemFile = (IChemFile) reader.read(new ChemFile());
        Assert.assertNotNull(chemFile);
        Assert.assertEquals(1, chemFile.getChemSequenceCount());

        org.openscience.cdk.interfaces.IChemSequence seq = chemFile.getChemSequence(0);
        Assert.assertNotNull(seq);
        Assert.assertEquals(1, seq.getChemModelCount());

        IChemModel model = seq.getChemModel(0);
        Assert.assertNotNull(model);
        Assert.assertEquals(1, model.getMoleculeSet().getAtomContainerCount());

        IAtomContainer container = model.getMoleculeSet().getAtomContainer(0);
        Assert.assertTrue(container instanceof IBioPolymer);
        IBioPolymer polymer = (IBioPolymer) container;

        Assert.assertTrue(polymer instanceof PDBPolymer);
        PDBPolymer pdb = (PDBPolymer) polymer;
        Assert.assertEquals(4, pdb.getStrandCount());

        Assert.assertTrue(polymer.getStrandNames().contains("D"));
        Assert.assertTrue("Strand D is not a PDBStrand", polymer.getStrand("D") instanceof PDBStrand);
        Assert.assertTrue(polymer.getStrandNames().contains("E"));
        Assert.assertTrue("Strand E is not a PDBStrand", polymer.getStrand("E") instanceof PDBStrand);
        Assert.assertTrue(polymer.getStrandNames().contains("A"));
        Assert.assertTrue("Strand A is not a PDBStrand", polymer.getStrand("A") instanceof PDBStrand);
        Assert.assertTrue(polymer.getStrandNames().contains("B"));
        Assert.assertTrue("Strand B is not a PDBStrand", polymer.getStrand("B") instanceof PDBStrand);

        //Check to pick up all 4 strands
        Assert.assertEquals(polymer.getStrands().size(), 4);

        //The following check is to see that the first monomers in a strand
        //can be accessed consecutively
        //i.e. their resSeq numbering follows that in the File

        //Strand A
        PDBStrand strandA = (PDBStrand) polymer.getStrand("A");
        Collection<String> lst = strandA.getMonomerNamesInSequentialOrder();

        //Should be 57 monomers in strand A
        Assert.assertEquals(57, lst.size());
        Iterator<String> lstIter = lst.iterator();

        String monomer1 = lstIter.next();
        IMonomer mono1 = strandA.getMonomer(monomer1);
        Assert.assertNotNull(mono1);
        Assert.assertNotNull(mono1.getMonomerName());
        Assert.assertTrue("Monomer is not a PDBMonomer", mono1 instanceof PDBMonomer);
        PDBMonomer pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("A", pdbMonomer.getChainID());
        Assert.assertEquals("8", pdbMonomer.getResSeq());

        monomer1 = lstIter.next();
        mono1 = strandA.getMonomer(monomer1);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("A", pdbMonomer.getChainID());
        Assert.assertEquals("9", pdbMonomer.getResSeq());

        monomer1 = lstIter.next();
        mono1 = strandA.getMonomer(monomer1);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("A", pdbMonomer.getChainID());
        Assert.assertEquals("10", pdbMonomer.getResSeq());

        //Strand B
        PDBStrand strandB = (PDBStrand) polymer.getStrand("B");
        lst = strandB.getMonomerNamesInSequentialOrder();

        //Should be 57 monomers in strand B
        Assert.assertEquals(57, lst.size());
        lstIter = lst.iterator();

        monomer1 = lstIter.next();
        mono1 = strandB.getMonomer(monomer1);
        Assert.assertNotNull(mono1);
        Assert.assertNotNull(mono1.getMonomerName());
        Assert.assertTrue("Monomer is not a PDBMonomer", mono1 instanceof PDBMonomer);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("B", pdbMonomer.getChainID());
        Assert.assertEquals("8", pdbMonomer.getResSeq());

        monomer1 = lstIter.next();
        mono1 = strandB.getMonomer(monomer1);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("B", pdbMonomer.getChainID());
        Assert.assertEquals("9", pdbMonomer.getResSeq());

        monomer1 = lstIter.next();
        mono1 = strandB.getMonomer(monomer1);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("B", pdbMonomer.getChainID());
        Assert.assertEquals("10", pdbMonomer.getResSeq());

        //Strand E
        PDBStrand strandE = (PDBStrand) polymer.getStrand("E");
        lst = strandE.getMonomerNamesInSequentialOrder();

        //Should be 19 monomers in strand E
        Assert.assertEquals(19, lst.size());
        lstIter = lst.iterator();

        monomer1 = lstIter.next();
        mono1 = strandE.getMonomer(monomer1);
        Assert.assertNotNull(mono1);
        Assert.assertNotNull(mono1.getMonomerName());
        Assert.assertTrue("Monomer is not a PDBMonomer", mono1 instanceof PDBMonomer);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("E", pdbMonomer.getChainID());
        Assert.assertEquals("20", pdbMonomer.getResSeq());

        monomer1 = lstIter.next();
        mono1 = strandE.getMonomer(monomer1);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("E", pdbMonomer.getChainID());
        Assert.assertEquals("21", pdbMonomer.getResSeq());

        monomer1 = lstIter.next();
        mono1 = strandE.getMonomer(monomer1);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("E", pdbMonomer.getChainID());
        Assert.assertEquals("22", pdbMonomer.getResSeq());

        //Chain D should be 1,2,3...19
        PDBStrand strandD = (PDBStrand) polymer.getStrand("D");
        lst = strandD.getMonomerNamesInSequentialOrder();

        //Should be 19 monomers in strand D
        Assert.assertEquals(19, lst.size());
        lstIter = lst.iterator();

        monomer1 = lstIter.next();
        mono1 = strandD.getMonomer(monomer1);
        Assert.assertNotNull(mono1);
        Assert.assertNotNull(mono1.getMonomerName());
        Assert.assertTrue("Monomer is not a PDBMonomer", mono1 instanceof PDBMonomer);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("D", pdbMonomer.getChainID());
        Assert.assertEquals("1", pdbMonomer.getResSeq());

        monomer1 = lstIter.next();
        mono1 = strandD.getMonomer(monomer1);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("D", pdbMonomer.getChainID());
        Assert.assertEquals("2", pdbMonomer.getResSeq());

        monomer1 = lstIter.next();
        mono1 = strandD.getMonomer(monomer1);
        pdbMonomer = (PDBMonomer) mono1;
        Assert.assertEquals("D", pdbMonomer.getChainID());
        Assert.assertEquals("3", pdbMonomer.getResSeq());

        // PDB Structures validation
        //Should have 6 helices
        Assert.assertEquals(6, pdb.getStructures().size());

    }

}