/**
 * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
 * This file is part of CSipSimple.
 *
 *  CSipSimple is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  If you own a pjsip commercial license you can also redistribute it
 *  and/or modify it under the terms of the GNU Lesser General Public License
 *  as an android library.
 *
 *  CSipSimple is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with CSipSimple.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.voiceblue.phone.pjsip.recorder.impl;

import android.content.Intent;
import android.text.format.DateFormat;

import com.voiceblue.phone.api.SipCallSession;
import com.voiceblue.phone.api.SipManager;
import com.voiceblue.phone.pjsip.recorder.IRecorderHandler;
import com.voiceblue.phone.service.SipService.SameThreadException;

import org.pjsip.pjsua.pj_str_t;
import org.pjsip.pjsua.pjsua;

import java.io.File;
import java.io.IOException;
import java.util.Date;

public class SimpleWavRecorderHandler implements IRecorderHandler {
    final int way;
    final SipCallSession callInfo;
    private final int recorderId;
    private final String recordingPath;

    public SimpleWavRecorderHandler(SipCallSession callInfo, File recordFolder, int way)
            throws SameThreadException, IOException {
        this.way = way;
        this.callInfo = callInfo;

        File targetFile = getRecordFile(recordFolder, callInfo.getRemoteContact(), way);
        if (targetFile == null) {
            throw new IOException("No target file possible");
        }
        recordingPath = targetFile.getAbsolutePath();
        pj_str_t file = pjsua.pj_str_copy(recordingPath);
        int[] rcId = new int[1];
        int status = pjsua.recorder_create(file, 0, (byte[]) null, 0, 0, rcId);
        if (status == pjsua.PJ_SUCCESS) {
            recorderId = rcId[0];
        } else {
            throw new IOException("Pjsip not able to write the file");
        }
    }

    /**
     * Get the file to record to for a given remote contact. This will
     * implicitly get the current date in file name.
     * 
     * @param remoteContact The remote contact name
     * @return The file to store conversation
     */
    private File getRecordFile(File dir, String remoteContact, int way) {
        if (dir != null) {
            // The file name is only to have an unique identifier.
            // It should never be used to store datas as may change.
            // The app using the recording files should rely on the broadcast
            // and on callInfo instead that is reliable.
            String datePart = (String) DateFormat.format("yy-MM-dd_kkmmss", new Date());
            String remotePart = sanitizeForFile(remoteContact);
            String fileName = datePart + "_" + remotePart;
            if (way != (SipManager.BITMASK_ALL)) {
                fileName += ((way & SipManager.BITMASK_IN) == 0) ? "_out" : "_in";
            }
            File file = new File(dir.getAbsoluteFile() + File.separator
                    + fileName + ".wav");
            return file;
        }
        return null;
    }

    private String sanitizeForFile(String remoteContact) {
        String fileName = remoteContact;
        fileName = fileName.replaceAll("[\\.\\\\<>:; \"\'\\*]", "_");
        return fileName;
    }

    @Override
    public void startRecording() {
        // TODO : treat connect errors ? is it useful? Should we fail gracefully
        int wavPort = pjsua.recorder_get_conf_port(recorderId);
        if ((way & SipManager.BITMASK_IN) == SipManager.BITMASK_IN) {
            int wavConfPort = callInfo.getConfPort();
            pjsua.conf_connect(wavConfPort, wavPort);
        }
        if ((way & SipManager.BITMASK_OUT) == SipManager.BITMASK_OUT) {
            pjsua.conf_connect(0, wavPort);
        }
    }

    @Override
    public void stopRecording() {
        pjsua.recorder_destroy(recorderId);
    }

    @Override
    public void fillBroadcastWithInfo(Intent it) {
        it.putExtra(SipManager.EXTRA_FILE_PATH, recordingPath);
        it.putExtra(SipManager.EXTRA_SIP_CALL_CALL_WAY, way);
    }

}
