/* -*- c++ -*- */
/*
 * @file
 * @author Piotr Krysik <ptrkrysik@gmail.com>
 * @section LICENSE
 *
 * Gr-gsm 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, or (at your option)
 * any later version.
 *
 * Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include <grgsm/gsmtap.h>
#include <unistd.h>
#include <set>
#include <iterator>
#include <algorithm>
#include <iostream>

#include "extract_system_info_impl.h"

namespace gr {
  namespace gsm {
    boost::mutex extract_mutex;
    void extract_system_info_impl::process_bursts(pmt::pmt_t msg)
    {
        pmt::pmt_t burst_plus_header_blob = pmt::cdr(msg);
        gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(burst_plus_header_blob);

        chan_info info;
        info.id = header->arfcn;
        info.pwr_db = header->signal_dbm;
        std::set<chan_info, compare_id>::iterator iter = d_c0_channels.find(info);

        boost::mutex::scoped_lock lock(extract_mutex);
        if(iter != d_c0_channels.end()){
            info.lac = iter->lac;
            info.cell_id = iter->cell_id;
            info.mnc = iter->mnc;
            d_c0_channels.erase(iter);
            d_c0_channels.insert(info);
        } 
        d_c0_channels.insert(info);
    }
    
    void extract_system_info_impl::process_sysinfo(pmt::pmt_t msg){
        pmt::pmt_t message_plus_header_blob = pmt::cdr(msg);
        uint8_t * message_plus_header = (uint8_t *)pmt::blob_data(message_plus_header_blob);
        gsmtap_hdr * header = (gsmtap_hdr *)message_plus_header;
        uint8_t * msg_elements = (uint8_t *)(message_plus_header+sizeof(gsmtap_hdr));

        if(msg_elements[2]==0x1b){
            //wyciągnij arfcn
            pmt::pmt_t header_blob = pmt::car(msg);
            gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_blob);
            chan_info info;
            info.id = header->arfcn;
            info.pwr_db = header->signal_dbm;
            info.cell_id = (msg_elements[3]<<8)+msg_elements[4];         //take cell id
            info.lac = (msg_elements[8]<<8)+msg_elements[9];             //take lac
            info.mnc = (msg_elements[7]>>4);                             //take mnc

            std::set<chan_info, compare_id>::iterator iter = d_c0_channels.find(info);
            boost::mutex::scoped_lock lock(extract_mutex);
            if(iter != d_c0_channels.end()){
                d_c0_channels.erase(iter);
            }
            d_c0_channels.insert(info);
        }
        else if(msg_elements[2]==0x1c){
            pmt::pmt_t header_blob = pmt::car(msg);
            gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_blob);
            chan_info info;
            info.id = header->arfcn;
            info.pwr_db = header->signal_dbm;
            info.lac = (msg_elements[6]<<8)+msg_elements[7];       //take lac
            info.mnc = (msg_elements[5]>>4);                       //take mnc

            std::set<chan_info, compare_id>::iterator iter = d_c0_channels.find(info);
            boost::mutex::scoped_lock lock(extract_mutex);
            if(iter != d_c0_channels.end()){
                d_c0_channels.erase(iter);
                if(iter->cell_id!=0){
                    info.cell_id=iter->cell_id;
                }
            }
            d_c0_channels.insert(info);
        }
    }
    
    void extract_system_info_impl::show(){
        std::vector<chan_info> chans(d_c0_channels.begin(), d_c0_channels.end()); 
        std::vector<chan_info>::iterator iter;
        //std::sort(chans.begin(), chans.end(), compare_pwr());
        for(iter=chans.begin(); iter != chans.end(); ++iter){
            std::cout << static_cast<int>((*iter).id) << "(" << static_cast<int>((*iter).pwr_db) << ") ";
        }
        std::cout << std::endl;
    }
    
    std::vector<int> extract_system_info_impl::get_chans()
    {
        std::vector<chan_info> chans(d_c0_channels.begin(), d_c0_channels.end()); 
        std::vector<int> chans_ids(chans.size(),-1);
        //std::sort(chans.begin(), chans.end(), compare_pwr());

        for(int ii; ii < chans.size(); ++ii){
            chans_ids[ii] = chans[ii].id;
        }
        
        return chans_ids;
    }
    
    std::vector<int> extract_system_info_impl::get_lac()
    {
        std::vector<chan_info> chans(d_c0_channels.begin(), d_c0_channels.end()); 
        std::vector<int> chans_ids(chans.size(),-1);
        //std::sort(chans.begin(), chans.end(), compare_pwr());

        for(int ii; ii < chans.size(); ++ii){
            chans_ids[ii] = chans[ii].lac;
        }
        
        return chans_ids;
    }
    std::vector<int> extract_system_info_impl::get_mnc()
    {
        std::vector<chan_info> chans(d_c0_channels.begin(), d_c0_channels.end()); 
        std::vector<int> chans_ids(chans.size(),-1);
        //std::sort(chans.begin(), chans.end(), compare_pwr());

        for(int ii; ii < chans.size(); ++ii){
            chans_ids[ii] = chans[ii].mnc;
        }
        
        return chans_ids;
    }
    std::vector<int> extract_system_info_impl::get_cell_id()
    {
        std::vector<chan_info> chans(d_c0_channels.begin(), d_c0_channels.end()); 
        std::vector<int> chans_ids(chans.size(),-1);
        //std::sort(chans.begin(), chans.end(), compare_pwr());

        for(int ii; ii < chans.size(); ++ii){
            chans_ids[ii] = chans[ii].cell_id;
        }
        
        return chans_ids;
    }
    
    std::vector<int> extract_system_info_impl::get_pwrs()
    {
        std::vector<chan_info> chans(d_c0_channels.begin(), d_c0_channels.end()); 
        std::vector<int> pwrs(chans.size(),-1);
        //std::sort(chans.begin(), chans.end(), compare_pwr());

        for(int ii; ii < chans.size(); ++ii){
            pwrs[ii] = chans[ii].pwr_db;
        }
        
        return pwrs;
    }
    
    void extract_system_info_impl::reset()
    {
        std::set<chan_info, compare_id>::iterator iter;
        
        chan_info info;

        for(iter = d_c0_channels.begin(); iter != d_c0_channels.end(); iter++){
            info.id = iter->id;
            info.cell_id = iter->cell_id;    
            info.lac = iter->lac;            
            info.mnc = iter->mnc;           
            info.pwr_db = -111;
            d_c0_channels.erase(iter);
            d_c0_channels.insert(info);
        }
//        d_c0_channels.clear();
        
        if(!empty_p(pmt::mp("bursts"))){
            delete_head_blocking(pmt::mp("bursts"));
        }
    }
    
    extract_system_info::sptr
    extract_system_info::make()
    {
      return gnuradio::get_initial_sptr
        (new extract_system_info_impl());
    }

    /*
     * The private constructor
     */
    extract_system_info_impl::extract_system_info_impl()
      : gr::block("extract_system_info",
              gr::io_signature::make(0, 0, 0),
              gr::io_signature::make(0, 0, 0)), 
              after_reset(false)
    {
        message_port_register_in(pmt::mp("bursts"));
        set_msg_handler(pmt::mp("bursts"), boost::bind(&extract_system_info_impl::process_bursts, this, _1));
        message_port_register_in(pmt::mp("msgs"));
        set_msg_handler(pmt::mp("msgs"), boost::bind(&extract_system_info_impl::process_sysinfo, this, _1));
    }
    
    /*
     * Our virtual destructor.
     */
    extract_system_info_impl::~extract_system_info_impl()
    {
    }


  } /* namespace gsm */
} /* namespace gr */

