#    Copyright 2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from __future__ import division
import os
import tempfile
import csv
import time
import pexpect

from devlib.platform import Platform
from devlib.instrument import Instrument, InstrumentChannel, MeasurementsCsv, Measurement,  CONTINUOUS,  INSTANTANEOUS
from devlib.exception import TargetError, HostError
from devlib.host import PACKAGE_BIN_DIRECTORY
from devlib.utils.serial_port import open_serial_connection


class VersatileExpressPlatform(Platform):

    def __init__(self, name,  # pylint: disable=too-many-locals

                 core_names=None,
                 core_clusters=None,
                 big_core=None,
                 modules=None,

                 # serial settings
                 serial_port='/dev/ttyS0',
                 baudrate=115200,

                 # VExpress MicroSD mount point
                 vemsd_mount=None,

                 # supported: dtr, reboottxt
                 hard_reset_method=None,
                 # supported: uefi, uefi-shell, u-boot, bootmon
                 bootloader=None,
                 # supported: vemsd
                 flash_method='vemsd',

                 image=None,
                 fdt=None,
                 initrd=None,
                 bootargs=None,

                 uefi_entry=None,  # only used if bootloader is "uefi"
                 ready_timeout=60,
                 ):
        super(VersatileExpressPlatform, self).__init__(name,
                                                       core_names,
                                                       core_clusters,
                                                       big_core,
                                                       modules)
        self.serial_port = serial_port
        self.baudrate = baudrate
        self.vemsd_mount = vemsd_mount
        self.image = image
        self.fdt = fdt
        self.initrd = initrd
        self.bootargs = bootargs
        self.uefi_entry = uefi_entry
        self.ready_timeout = ready_timeout
        self.bootloader = None
        self.hard_reset_method = None
        self._set_bootloader(bootloader)
        self._set_hard_reset_method(hard_reset_method)
        self._set_flash_method(flash_method)

    def init_target_connection(self, target):
        if target.os == 'android':
            self._init_android_target(target)
        else:
            self._init_linux_target(target)

    def _init_android_target(self, target):
        if target.connection_settings.get('device') is None:
            addr = self._get_target_ip_address(target)
            target.connection_settings['device'] = addr + ':5555'

    def _init_linux_target(self, target):
        if target.connection_settings.get('host') is None:
            addr = self._get_target_ip_address(target)
            target.connection_settings['host'] = addr

    def _get_target_ip_address(self, target):
        with open_serial_connection(port=self.serial_port,
                                    baudrate=self.baudrate,
                                    timeout=30,
                                    init_dtr=0) as tty:
            tty.sendline('')
            self.logger.debug('Waiting for the Android shell prompt.')
            tty.expect(target.shell_prompt)

            self.logger.debug('Waiting for IP address...')
            wait_start_time = time.time()
            while True:
                tty.sendline('ip addr list eth0')
                time.sleep(1)
                try:
                    tty.expect(r'inet ([1-9]\d*.\d+.\d+.\d+)', timeout=10)
                    return tty.match.group(1)
                except pexpect.TIMEOUT:
                    pass  # We have our own timeout -- see below.
                if (time.time() - wait_start_time) > self.ready_timeout:
                    raise TargetError('Could not acquire IP address.')

    def _set_hard_reset_method(self, hard_reset_method):
        if hard_reset_method == 'dtr':
            self.modules.append({'vexpress-dtr': {'port': self.serial_port,
                                                  'baudrate': self.baudrate,
                                                  }})
        elif hard_reset_method == 'reboottxt':
            self.modules.append({'vexpress-reboottxt': {'port': self.serial_port,
                                                        'baudrate': self.baudrate,
                                                        'path': self.vemsd_mount,
                                                        }})
        else:
            ValueError('Invalid hard_reset_method: {}'.format(hard_reset_method))

    def _set_bootloader(self, bootloader):
        self.bootloader = bootloader
        if self.bootloader == 'uefi':
            self.modules.append({'vexpress-uefi': {'port': self.serial_port,
                                                   'baudrate': self.baudrate,
                                                   'image': self.image,
                                                   'fdt': self.fdt,
                                                   'initrd': self.initrd,
                                                   'bootargs': self.bootargs,
                                                   }})
        elif self.bootloader == 'uefi-shell':
            self.modules.append({'vexpress-uefi-shell': {'port': self.serial_port,
                                                         'baudrate': self.baudrate,
                                                         'image': self.image,
                                                         'bootargs': self.bootargs,
                                                         }})
        elif self.bootloader == 'u-boot':
            uboot_env = None
            if self.bootargs:
                uboot_env = {'bootargs': self.bootargs}
            self.modules.append({'vexpress-u-boot': {'port': self.serial_port,
                                                     'baudrate': self.baudrate,
                                                     'env': uboot_env,
                                                     }})
        elif self.bootloader == 'bootmon':
            self.modules.append({'vexpress-bootmon': {'port': self.serial_port,
                                                      'baudrate': self.baudrate,
                                                      'image': self.image,
                                                      'fdt': self.fdt,
                                                      'initrd': self.initrd,
                                                      'bootargs': self.bootargs,
                                                      }})
        else:
            ValueError('Invalid hard_reset_method: {}'.format(bootloader))

    def _set_flash_method(self, flash_method):
        if flash_method == 'vemsd':
            self.modules.append({'vexpress-vemsd': {'vemsd_mount': self.vemsd_mount}})
        else:
            ValueError('Invalid flash_method: {}'.format(flash_method))


class Juno(VersatileExpressPlatform):

    def __init__(self,
                 vemsd_mount='/media/JUNO',
                 baudrate=115200,
                 bootloader='u-boot',
                 hard_reset_method='dtr',
                 **kwargs
                 ):
        super(Juno, self).__init__('juno',
                                   vemsd_mount=vemsd_mount,
                                   baudrate=baudrate,
                                   bootloader=bootloader,
                                   hard_reset_method=hard_reset_method,
                                   **kwargs)


class TC2(VersatileExpressPlatform):

    def __init__(self,
                 vemsd_mount='/media/VEMSD',
                 baudrate=38400,
                 bootloader='bootmon',
                 hard_reset_method='reboottxt',
                 **kwargs
                 ):
        super(TC2, self).__init__('tc2',
                                  vemsd_mount=vemsd_mount,
                                  baudrate=baudrate,
                                  bootloader=bootloader,
                                  hard_reset_method=hard_reset_method,
                                  **kwargs)


class JunoEnergyInstrument(Instrument):

    binname = 'readenergy'
    mode = CONTINUOUS | INSTANTANEOUS

    _channels = [
        InstrumentChannel('sys', 'current'),
        InstrumentChannel('a57', 'current'),
        InstrumentChannel('a53', 'current'),
        InstrumentChannel('gpu', 'current'),
        InstrumentChannel('sys', 'voltage'),
        InstrumentChannel('a57', 'voltage'),
        InstrumentChannel('a53', 'voltage'),
        InstrumentChannel('gpu', 'voltage'),
        InstrumentChannel('sys', 'power'),
        InstrumentChannel('a57', 'power'),
        InstrumentChannel('a53', 'power'),
        InstrumentChannel('gpu', 'power'),
        InstrumentChannel('sys', 'energy'),
        InstrumentChannel('a57', 'energy'),
        InstrumentChannel('a53', 'energy'),
        InstrumentChannel('gpu', 'energy'),
    ]

    def __init__(self, target):
        super(JunoEnergyInstrument, self).__init__(target)
        self.on_target_file = None
        self.command = None
        self.binary = self.target.bin(self.binname)
        for chan in self._channels:
            self.channels[chan.name] = chan
        self.on_target_file = self.target.tempfile('energy', '.csv')
        self.sample_rate_hz = 10 # DEFAULT_PERIOD is 100[ms] in readenergy.c
        self.command = '{} -o {}'.format(self.binary, self.on_target_file)
        self.command2 = '{}'.format(self.binary)

    def setup(self):
        self.binary = self.target.install(os.path.join(PACKAGE_BIN_DIRECTORY,
                                                       self.target.abi, self.binname))

    def reset(self, sites=None, kinds=None):
        super(JunoEnergyInstrument, self).reset(sites, kinds)
        self.target.killall(self.binname, as_root=True)

    def start(self):
        self.target.kick_off(self.command, as_root=True)

    def stop(self):
        self.target.killall(self.binname, signal='TERM', as_root=True)

    def get_data(self, output_file):
        temp_file = tempfile.mktemp()
        self.target.pull(self.on_target_file, temp_file)
        self.target.remove(self.on_target_file)

        with open(temp_file, 'rb') as fh:
            reader = csv.reader(fh)
            headings = reader.next()

            # Figure out which columns from the collected csv we actually want
            select_columns = []
            for chan in self.active_channels:
                try:
                    select_columns.append(headings.index(chan.name))
                except ValueError:
                    raise HostError('Channel "{}" is not in {}'.format(chan.name, temp_file))

            with open(output_file, 'wb') as wfh:
                write_headings = ['{}_{}'.format(c.site, c.kind)
                                  for c in self.active_channels]
                writer = csv.writer(wfh)
                writer.writerow(write_headings)
                for row in reader:
                    write_row = [row[c] for c in select_columns]
                    writer.writerow(write_row)

        return MeasurementsCsv(output_file, self.active_channels)

    def take_measurement(self):
        result = []
        output = self.target.execute(self.command2).split()
        reader=csv.reader(output)
        headings=reader.next()
        values = reader.next()
        for chan in self.active_channels:
            value = values[headings.index(chan.name)]
            result.append(Measurement(value, chan))
        return result

