# Path: ssbio/protein/structure/utils/structureio.py
# class StructureIO(PDBIO):
#     """Extended class to load any structure file into a Biopython Structure object
# 
#     Loads the first model when there are multiple available.
#     Also adds some logging methods.
#     """
# 
#     # XTODO: need to revamp this module to be clearer on what files are supported, how file path is parsed
#     # (should explicitly define it)
#     def __init__(self, structure_file, file_type=None):
#         PDBIO.__init__(self)
# 
#         dirname, filename_without_extension, file_type2 = ssbio.utils.split_folder_and_path(structure_file)
#         self.structure_file = structure_file
# 
#         # Unzip the file if it is zipped
#         if file_type == '.gz':
#             unzipped = ssbio.utils.gunzip_file(structure_file, outdir=dirname)
#             dirname, filename_without_extension, file_type2 = ssbio.utils.split_folder_and_path(unzipped)
# 
#         if not file_type:
#             file_type = file_type2
#         else:
#             if '.' not in file_type:
#                 file_type = '.{}'.format(file_type)
# 
#         if file_type.lower() in ['.pdb', '.ent', '.mmcif', '.cif', '.mmtf']:
#             # Load the structure
#             if file_type.lower() == '.pdb' or file_type.lower() == '.ent':
#                 structure = pdbp.get_structure(id='ssbio_pdb', file=structure_file)
#             if file_type.lower() == '.mmcif' or file_type.lower() == '.cif':
#                 with warnings.catch_warnings():
#                     warnings.simplefilter('ignore', PDBConstructionWarning)
#                     structure = cifp.get_structure(structure_id='ssbio_cif', filename=structure_file)
#             if file_type.lower() == '.mmtf':
#                 with warnings.catch_warnings():
#                     warnings.simplefilter('ignore', PDBConstructionWarning)
#                     structure = mmtfp.get_structure(file_path=structure_file)
#             log.debug('{}: parsed 3D coordinates of structure'.format(op.basename(structure_file)))
#         else:
#             raise ValueError('{}: unsupported file type'.format(file_type))
# 
#         self.set_structure(structure)
#         try:
#             self.first_model = structure[0]
#         except KeyError:
#             raise KeyError('{}: no models contained in structure! Please check structure file contents.'.format(structure_file))
# 
#     def write_pdb(self, custom_name='', out_suffix='', out_dir=None, custom_selection=None, force_rerun=False):
#         """Write a new PDB file for the Structure's FIRST MODEL.
# 
#         Set custom_selection to a PDB.Select class for custom SMCRA selections.
# 
#         Args:
#             custom_name: Filename of the new file (without extension)
#             out_suffix: Optional string to append to new PDB file
#             out_dir: Optional directory to output the file
#             custom_selection: Optional custom selection class
#             force_rerun: If existing file should be overwritten
# 
#         Returns:
#             out_file: filepath of new PDB file
# 
#         """
#         if not custom_selection:
#             custom_selection = ModelSelection([0])
# 
#         # If no output directory, custom name, or suffix is specified, add a suffix "_new"
#         if not out_dir or not custom_name:
#             if not out_suffix:
#                 out_suffix = '_new'
# 
#         # Prepare the output file path
#         outfile = ssbio.utils.outfile_maker(inname=self.structure_file,
#                                             outname=custom_name,
#                                             append_to_name=out_suffix,
#                                             outdir=out_dir,
#                                             outext='.pdb')
#         try:
#             if ssbio.utils.force_rerun(flag=force_rerun, outfile=outfile):
#                 self.save(outfile, custom_selection)
#         except TypeError as e:
#             # If trying to save something that can't be saved as a PDB (example: 5iqr.cif), log an error and return None
#             # The error thrown by PDBIO.py is "TypeError: %c requires int or char"
#             log.error('{}: unable to save structure in PDB file format'.format(self.structure_file))
#             raise TypeError(e)
# 
#         return outfile


import argparse
import logging
import os
import os.path as op
import textwrap
import ssbio.utils
from Bio import PDB
from tqdm import tqdm
from ssbio.protein.structure.utils.structureio import StructureIO
              remove_atom_alt=True, keep_atom_alt_id='A', remove_atom_hydrogen=True, add_atom_occ=True,
              remove_res_hetero=True, keep_chemicals=None, keep_res_only=None,
              add_chain_id_if_empty='X', keep_chains=None):
    """Clean a PDB file.

    Args:
        pdb_file (str): Path to input PDB file
        out_suffix (str): Suffix to append to original filename
        outdir (str): Path to output directory
        force_rerun (bool): If structure should be re-cleaned if a clean file exists already
        remove_atom_alt (bool): Remove alternate positions
        keep_atom_alt_id (str): If removing alternate positions, which alternate ID to keep
        remove_atom_hydrogen (bool): Remove hydrogen atoms
        add_atom_occ (bool): Add atom occupancy fields if not present
        remove_res_hetero (bool): Remove all HETATMs
        keep_chemicals (str, list): If removing HETATMs, keep specified chemical names
        keep_res_only (str, list): Keep ONLY specified resnames, deletes everything else!
        add_chain_id_if_empty (str): Add a chain ID if not present
        keep_chains (str, list): Keep only these chains

    Returns:
        str: Path to cleaned PDB file

    """
    outfile = ssbio.utils.outfile_maker(inname=pdb_file,
                                        append_to_name=out_suffix,
                                        outdir=outdir,
                                        outext='.pdb')

    if ssbio.utils.force_rerun(flag=force_rerun, outfile=outfile):

# Path: ssbio/protein/structure/utils/structureio.py
# class StructureIO(PDBIO):
#     """Extended class to load any structure file into a Biopython Structure object
# 
#     Loads the first model when there are multiple available.
#     Also adds some logging methods.
#     """
# 
#     # XTODO: need to revamp this module to be clearer on what files are supported, how file path is parsed
#     # (should explicitly define it)
#     def __init__(self, structure_file, file_type=None):
#         PDBIO.__init__(self)
# 
#         dirname, filename_without_extension, file_type2 = ssbio.utils.split_folder_and_path(structure_file)
#         self.structure_file = structure_file
# 
#         # Unzip the file if it is zipped
#         if file_type == '.gz':
#             unzipped = ssbio.utils.gunzip_file(structure_file, outdir=dirname)
#             dirname, filename_without_extension, file_type2 = ssbio.utils.split_folder_and_path(unzipped)
# 
#         if not file_type:
#             file_type = file_type2
#         else:
#             if '.' not in file_type:
#                 file_type = '.{}'.format(file_type)
# 
#         if file_type.lower() in ['.pdb', '.ent', '.mmcif', '.cif', '.mmtf']:
#             # Load the structure
#             if file_type.lower() == '.pdb' or file_type.lower() == '.ent':
#                 structure = pdbp.get_structure(id='ssbio_pdb', file=structure_file)
#             if file_type.lower() == '.mmcif' or file_type.lower() == '.cif':
#                 with warnings.catch_warnings():
#                     warnings.simplefilter('ignore', PDBConstructionWarning)
#                     structure = cifp.get_structure(structure_id='ssbio_cif', filename=structure_file)
#             if file_type.lower() == '.mmtf':
#                 with warnings.catch_warnings():
#                     warnings.simplefilter('ignore', PDBConstructionWarning)
#                     structure = mmtfp.get_structure(file_path=structure_file)
#             log.debug('{}: parsed 3D coordinates of structure'.format(op.basename(structure_file)))
#         else:
#             raise ValueError('{}: unsupported file type'.format(file_type))
# 
#         self.set_structure(structure)
#         try:
#             self.first_model = structure[0]
#         except KeyError:
#             raise KeyError('{}: no models contained in structure! Please check structure file contents.'.format(structure_file))
# 
#     def write_pdb(self, custom_name='', out_suffix='', out_dir=None, custom_selection=None, force_rerun=False):
#         """Write a new PDB file for the Structure's FIRST MODEL.
# 
#         Set custom_selection to a PDB.Select class for custom SMCRA selections.
# 
#         Args:
#             custom_name: Filename of the new file (without extension)
#             out_suffix: Optional string to append to new PDB file
#             out_dir: Optional directory to output the file
#             custom_selection: Optional custom selection class
#             force_rerun: If existing file should be overwritten
# 
#         Returns:
#             out_file: filepath of new PDB file
# 
#         """
#         if not custom_selection:
#             custom_selection = ModelSelection([0])
# 
#         # If no output directory, custom name, or suffix is specified, add a suffix "_new"
#         if not out_dir or not custom_name:
#             if not out_suffix:
#                 out_suffix = '_new'
# 
#         # Prepare the output file path
#         outfile = ssbio.utils.outfile_maker(inname=self.structure_file,
#                                             outname=custom_name,
#                                             append_to_name=out_suffix,
#                                             outdir=out_dir,
#                                             outext='.pdb')
#         try:
#             if ssbio.utils.force_rerun(flag=force_rerun, outfile=outfile):
#                 self.save(outfile, custom_selection)
#         except TypeError as e:
#             # If trying to save something that can't be saved as a PDB (example: 5iqr.cif), log an error and return None
#             # The error thrown by PDBIO.py is "TypeError: %c requires int or char"
#             log.error('{}: unable to save structure in PDB file format'.format(self.structure_file))
#             raise TypeError(e)
# 
#         return outfile


# Path: ssbio/protein/structure/utils/cleanpdb.py
import argparse
import logging
import os
import os.path as op
import textwrap
import ssbio.utils
from Bio import PDB
from tqdm import tqdm
from ssbio.protein.structure.utils.structureio import StructureIO

              remove_atom_alt=True, keep_atom_alt_id='A', remove_atom_hydrogen=True, add_atom_occ=True,
              remove_res_hetero=True, keep_chemicals=None, keep_res_only=None,
              add_chain_id_if_empty='X', keep_chains=None):
    """Clean a PDB file.

    Args:
        pdb_file (str): Path to input PDB file
        out_suffix (str): Suffix to append to original filename
        outdir (str): Path to output directory
        force_rerun (bool): If structure should be re-cleaned if a clean file exists already
        remove_atom_alt (bool): Remove alternate positions
        keep_atom_alt_id (str): If removing alternate positions, which alternate ID to keep
        remove_atom_hydrogen (bool): Remove hydrogen atoms
        add_atom_occ (bool): Add atom occupancy fields if not present
        remove_res_hetero (bool): Remove all HETATMs
        keep_chemicals (str, list): If removing HETATMs, keep specified chemical names
        keep_res_only (str, list): Keep ONLY specified resnames, deletes everything else!
        add_chain_id_if_empty (str): Add a chain ID if not present
        keep_chains (str, list): Keep only these chains

    Returns:
        str: Path to cleaned PDB file

    """
    outfile = ssbio.utils.outfile_maker(inname=pdb_file,
                                        append_to_name=out_suffix,
                                        outdir=outdir,
                                        outext='.pdb')

    if ssbio.utils.force_rerun(flag=force_rerun, outfile=outfile):

        my_pdb = StructureIO(pdb_file)