package ru.bitel.bgbilling.modules.voice.dyn.mediator.m200;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import ru.bitel.bgbilling.apps.voice.accounting.mediation.VoiceRecord;
import ru.bitel.bgbilling.apps.voice.accounting.mediation.VoiceRecordProcessor;
import ru.bitel.bgbilling.modules.voice.common.bean.VoiceDevice;
import ru.bitel.bgbilling.modules.voice.common.bean.VoiceDeviceType;
import ru.bitel.bgbilling.modules.voice.common.mediation.Mediator;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.ParameterMap;
import ru.bitel.common.TimeUtils;
import ru.bitel.common.Utils;

/**
 * Медиатор m200. Берет из папки файлы вида
сdr_log_01_06_2017.log
cdr_log_02_06_2017.log
cdr_log_03_06_2017.log
cdr_log_04_06_2017.log
cdr_log_05_06_2017.log
cdr_log_06_06_2017.log
cdr_log_07_06_2017.log

И помещает их в 0-вой час каждого дня 
 * 
 */

public class M200Mediator
    implements Mediator
{
    private static final Logger logger = LogManager.getLogger();
    private static final String FILE_PREFIX = "cdr_log_";
    private static final String REGION_PREFIX = "7861";
    
    private VoiceDevice device;
    @Override
    public Object init( Setup setup, int moduleId, VoiceDevice device, VoiceDeviceType deviceType, ParameterMap config )
        throws Exception
    {
        this.device = device;
        return null;
    }

    @Override
    public void readHourDataLog( VoiceRecordProcessor processor, Date hour )
        throws Exception
    {
        InputStream is = null;
        BufferedReader reader = null;
        
         
        String path = device.getLogPath();
        
        Calendar calHour = TimeUtils.convertDateToCalendar( hour );
        
        //обрабаьываем запросы только на нулевой час 
        if ( calHour.get( Calendar.HOUR_OF_DAY ) != 0 )
        {
            return;
        }
        
        
        try
        {
            String fullPath = path + "/" + FILE_PREFIX +  TimeUtils.format( hour, "dd_MM_yyyy" ) + ".log";
            
            //TODO переделать чтение на java.nio2 
            File file = new File( fullPath );
            
            
            if ( file.exists() )
            {
               is = new FileInputStream( file );
            }
            
            if ( is == null )
            {
                logger.warn( "log for " + hour +  " is empty" );
                return;
            }
    
            reader = new BufferedReader( new InputStreamReader( is ), 128 * 1024 );

            //final Pattern pattern = Pattern.compile( "\\t" );

            String line;
            while( (line = reader.readLine()) != null )
            {
                String[] params = line.split( " " );

                if( params.length == 11 )
                {
                    /*if( logger.isDebugEnabled() )
                    {
                        logger.debug( "LINE: " + line );
                    }*/
                    processLine( processor, params );
                }
                else
                {
                    logger.warn( "Skip line: " + line );
                }
            }
        }
       
        finally
        {
            
            if ( reader != null )
            {
                reader.close();
            }
            
            if ( is != null )
            {
                is.close();
            }
        }       
    }
    

    protected void processLine( final VoiceRecordProcessor processor, final String[] params )
        throws InterruptedException
    {
        String e164CallingStationId = params[4];
        String e164CalledStationId = params[5];
        
        String ansCode =  params[10];
        
        //отбрасывать можно звонки с кодом ответа 1
        if ( ansCode.equals( "1" ) || ansCode.equals( "27" ) || ansCode.equals( "34" ) ||  ansCode.equals( "134" ))
        {
            return;
        }
        
            
        /*//если исхоядщий порт начинается с A, номер вызываемого брать из вхоядщего порта( после буквы A) 
        if ( trunkIncoming.startsWith( "A" ) && trunkOutgoing.startsWith( "A" ))
        {
            e164CalledStationId = trunkIncoming.substring( 1 );    
        }
        */
        e164CallingStationId = prepareNumber( e164CallingStationId );
        e164CalledStationId = prepareNumber( e164CalledStationId );
        
        
        if ( e164CallingStationId.equals( "-") || e164CalledStationId.equals( "-" )  )
        {
            //игнорируем такие звонки. АТС их не пропустила
            return;
        }
        
        
        final VoiceRecord record = processor.next();
        
        record.trunkIncoming = params[0];
        record.callingStationId = params[1];
        record.calledStationId = params[2];        
        record.trunkOutgoing = params[3];
        record.e164CallingStationId = e164CallingStationId;
        record.e164CalledStationId = e164CalledStationId;
        String dateTime = params[6] + " " + params[7];        
        record.sessionStart = TimeUtils.parseDate( dateTime, "dd-MM-yy HH:mm:ss" );        
        record.connectionDuration = Utils.parseInt( params[8], 0 );        
        record.duration = Utils.parseInt( params[9], 0 );
    }   

    @Override
    public void getLogExists( Date month, int [] data )
    {
        String path = device.getLogPath();
        
        File rootDir = new File( path );
        if ( !rootDir.exists() )
        {
            return;
        }
                
        /*File monthDir  = new File( path + File.separator + new SimpleDateFormat( "yyyy/MM" ).format( month ) );
        
        if ( monthDir == null || !monthDir.exists() )
        {
            return;
        }*/
        
        Calendar calMonth = Calendar.getInstance();
        calMonth.setTime( month );
        
        
        String mm = String.format( "%02d", calMonth.get( Calendar.MONTH ) + 1 );
        String yy = String.format( "%04d", calMonth.get( Calendar.YEAR ) );
        
        //mm и yyyy мы заменяем чуть нижие
        String pattern = FILE_PREFIX + "(\\d{2})_" + mm + "_" + yy + ".log";
        
        Pattern patternRegexp = Pattern.compile( pattern );
        //rootDir.listFiles( f -> PATTERN_FILE.matcher( logFile.getName() ). );
        
        for ( File  logFile : rootDir.listFiles() )
        {
            Matcher matcher = patternRegexp.matcher( logFile.getName() );
            if ( matcher.find() )
            {
                String dd = matcher.group( 1 );
                
                //TODO parseByte
                byte day = (byte) Utils.parseInt( dd, -1 );
                
                //помещаем данные в 0-вой час 
                if ( day > 0 )
                {
                    data[day - 1] =  1;   
                }
                
            }
        }

    }
    
    private String prepareNumber( String number )
    {
        if ( number.length() == 10 )
        {
            return 7 + number; 
        }
        else if ( number.length() == 7 ) 
        {
            return REGION_PREFIX + number;
        }
        else if ( number.startsWith( "441" ) )
        {
            return number.substring( 3  );            
        }
        
        
        
        return number;
    }

}
