import time
import ldap
import logging
import pytest
from lib389 import DirSrv, Entry, tools, tasks
from lib389.tools import DirSrvTools
from lib389._constants import *
from lib389.properties import *
from lib389.tasks import *
from lib389.utils import *
from lib389.topologies import topology_m3 as topo

DEBUGGING = os.getenv("DEBUGGING", default=False)
if DEBUGGING:
    logging.getLogger(__name__).setLevel(logging.DEBUG)
else:
    logging.getLogger(__name__).setLevel(logging.INFO)
log = logging.getLogger(__name__)

CHANGELOG = 'cn=changelog5,cn=config'
MAXAGE_ATTR = 'nsslapd-changelogmaxage'
MAXAGE_INT = 30
MAXAGE_VALUE = str(MAXAGE_INT)
TRIMINTERVAL_INT = 5
TRIMINTERVAL = 'nsslapd-changelogtrim-interval'
USER_CN="user"

def toggle_ignorePreClean(server):
    dse_ref_ldif = server.confdir + '/dse.ldif'
    dse_new_ldif = server.confdir + '/dse.ldif.new'
    dse_ref = open(dse_ref_ldif, "r")
    dse_new = open(dse_new_ldif, "w")

    # Set nsds5ReplicaIgnorePreClean
    while True:
        line = dse_ref.readline()
        if (line == ''):
            break
        elif "nsds5replicaid" in line.lower():
            dse_new.write(line)
            new_line = "nsds5ReplicaIgnorePreClean: 1\n"
        else:
            new_line = line
        dse_new.write(new_line)

    dse_ref.close()
    dse_new.close()
    shutil.move(dse_new_ldif, dse_ref_ldif)
    
def add_user(server, no, desc='dummy', sleep=True):
    cn = '%s%d' % (USER_CN, no)
    dn = 'cn=%s,ou=people,%s' % (cn, SUFFIX)
    log.fatal('Adding user (%s): ' % dn)
    server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'inetuser', 'userSecurityInformation'],
                             'sn': ['_%s' % cn],
                             'description': [desc]})))
    time.sleep(1)

def check_user(server, no,):
    cn = '%s%d' % (USER_CN, no)
    dn = 'cn=%s,ou=people,%s' % (cn, SUFFIX)
    server.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)")

def test_ticket49446(topo):
    """Write your testcase here...

    Also, if you need any testcase initialization,
    please, write additional fixture for that(include finalizer).
    """
    
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    
    M1.stop()
    toggle_ignorePreClean(M1)
    M1.start()
    
    for s in (M1, M2, M3):
        s.modify_s("cn=config", [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', "8192")])
    
    m1_m2 = M1.agreement.list(suffix=SUFFIX, consumer_host=M2.host, consumer_port=M2.port)
    m1_m3 = M1.agreement.list(suffix=SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    m3_m1 = M3.agreement.list(suffix=SUFFIX, consumer_host=M1.host, consumer_port=M1.port)
    
    M1.modify_s(CHANGELOG, [(ldap.MOD_REPLACE, MAXAGE_ATTR, MAXAGE_VALUE),
                            (ldap.MOD_REPLACE, TRIMINTERVAL, str(TRIMINTERVAL_INT))])
    M2.modify_s(CHANGELOG, [(ldap.MOD_REPLACE, MAXAGE_ATTR, MAXAGE_VALUE),
                            (ldap.MOD_REPLACE, TRIMINTERVAL, str(TRIMINTERVAL_INT))])

    
    add_user(M1, 10, desc="add to M1")
    add_user(M2, 20, desc="add to M2")
    add_user(M3, 30, desc="add to M3")
    
    # important the user31 is the oldest csn in M2, because it will be cleared by changelog trimming
    add_user(M3, 31, desc="add to M3")
    add_user(M1, 11, desc="add to M1")
    add_user(M2, 21, desc="add to M2")
    time.sleep(40)
    
    # Here M1, M2, M3 should have 11,21,31 and 10,20,30 are CL cleared
    M2.stop()
    M1.agreement.pause(m1_m2[0].dn)
    add_user(M3, 32, desc="add to M3")
    add_user(M3, 33, desc="add to M3")
    add_user(M1, 12, desc="add to M1")
    M3.agreement.pause(m3_m1[0].dn)
    M3.agreement.resume(m3_m1[0].dn)
    time.sleep(40)
    
    # Here because of changelog trimming 31 and 32 are CL cleared

    # ClearRuv is launched but without Force
    M3.stop()
    M1.tasks.cleanAllRUV(suffix=SUFFIX, replicaid='3',
                        force=False, args={TASK_WAIT: False})
    # here M1 should clear 31
    M2.start()
    
    M1.agreement.pause(m1_m2[0].dn)
    M1.agreement.resume(m1_m2[0].dn)
    time.sleep(10)
    
    for i in (31, 11, 21, 32, 33, 12):
        check_user(M1, i)
    check_user(M2, 31)
    check_user(M2, 11)
    check_user(M2, 21)
    check_user(M2, 12)

    
    

    if DEBUGGING:
        # Add debugging steps(if any)...
        pass


if __name__ == '__main__':
    # Run isolated
    # -s for DEBUG mode
    CURRENT_FILE = os.path.realpath(__file__)
    pytest.main("-s %s" % CURRENT_FILE)

