# Copyright (C) 2020 Google LLC
#
# 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.

r"""Read APN conf xml file and output an textpb.

How to run:

update_apn.par --apn_file=./apns-full-conf.xml \
--data_dir=./data --out_file=/tmpapns.textpb
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import collections
from xml.dom import minidom
from google.protobuf import text_format

import carrier_list_pb2
import carrier_settings_pb2

parser = argparse.ArgumentParser()
parser.add_argument(
    '--apn_file', default='./apns-full-conf.xml', help='Path to APN xml file')
parser.add_argument(
    '--data_dir', default='./data', help='Folder path for CarrierSettings data')
parser.add_argument(
    '--out_file', default='./tmpapns.textpb', help='Temp APN file')
FLAGS = parser.parse_args()

CARRIER_LISTS = ['tier1_carriers.textpb', 'other_carriers.textpb']


def to_string(cid):
  """Return a string for CarrierId."""
  ret = cid.mcc_mnc
  if cid.HasField('spn'):
    ret += 'SPN=' + cid.spn.upper()
  if cid.HasField('imsi'):
    ret += 'IMSI=' + cid.imsi.upper()
  if cid.HasField('gid1'):
    ret += 'GID1=' + cid.gid1.upper()
  return ret


def get_cname(cid, known_carriers):
  """Return a canonical name based on cid and known_carriers.

  If found a match in known_carriers, return it. Otherwise generate a new one
  by concating the values.

  Args:
    cid: proto of CarrierId
    known_carriers: mapping from mccmnc and possible mvno data to canonical name

  Returns:
    string for canonical name, like verizon_us or 27402
  """
  name = to_string(cid)
  if name in known_carriers:
    return known_carriers[name]
  else:
    return name


def get_knowncarriers(files):
  """Create a mapping from mccmnc and possible mvno data to canonical name.

  Args:
    files: list of paths to carrier list textpb files

  Returns:
    A dict, key is to_string(carrier_id), value is cname.
  """
  ret = dict()
  for path in files:
    with open(path, 'r', encoding='utf-8') as f:
      carriers = text_format.Parse(f.read(), carrier_list_pb2.CarrierList())
      for carriermap in carriers.entry:
        # could print error if already exist
        for cid in carriermap.carrier_id:
          ret[to_string(cid)] = carriermap.canonical_name

  return ret


def gen_cid(apn_node):
  """Generate carrier id proto from APN node.

  Args:
    apn_node: DOM node from getElementsByTag

  Returns:
    CarrierId proto
  """
  ret = carrier_list_pb2.CarrierId()
  ret.mcc_mnc = (apn_node.getAttribute('mcc') + apn_node.getAttribute('mnc'))
  mvno_type = apn_node.getAttribute('mvno_type')
  mvno_data = apn_node.getAttribute('mvno_match_data')
  if mvno_type.lower() == 'spn':
    ret.spn = mvno_data
  if mvno_type.lower() == 'imsi':
    ret.imsi = mvno_data
  # in apn xml, gid means gid1, and no gid2
  if mvno_type.lower() == 'gid':
    ret.gid1 = mvno_data
  return ret


APN_TYPE_MAP = {
    '*': carrier_settings_pb2.ApnItem.ALL,
    'default': carrier_settings_pb2.ApnItem.DEFAULT,
    'internet': carrier_settings_pb2.ApnItem.DEFAULT,
    'vzw800': carrier_settings_pb2.ApnItem.DEFAULT,
    'mms': carrier_settings_pb2.ApnItem.MMS,
    'sup': carrier_settings_pb2.ApnItem.SUPL,
    'supl': carrier_settings_pb2.ApnItem.SUPL,
    'agps': carrier_settings_pb2.ApnItem.SUPL,
    'pam': carrier_settings_pb2.ApnItem.DUN,
    'dun': carrier_settings_pb2.ApnItem.DUN,
    'hipri': carrier_settings_pb2.ApnItem.HIPRI,
    'ota': carrier_settings_pb2.ApnItem.FOTA,
    'fota': carrier_settings_pb2.ApnItem.FOTA,
    'admin': carrier_settings_pb2.ApnItem.FOTA,
    'ims': carrier_settings_pb2.ApnItem.IMS,
    'cbs': carrier_settings_pb2.ApnItem.CBS,
    'ia': carrier_settings_pb2.ApnItem.IA,
    'emergency': carrier_settings_pb2.ApnItem.EMERGENCY,
    'xcap': carrier_settings_pb2.ApnItem.XCAP,
    'ut': carrier_settings_pb2.ApnItem.UT,
    'rcs': carrier_settings_pb2.ApnItem.RCS,
}


def map_apntype(typestr):
  """Map from APN type string to list of ApnType enums.

  Args:
    typestr: APN type string in apn conf xml, comma separated
  Returns:
    List of ApnType values in ApnItem proto.
  """
  typelist = [apn.strip().lower() for apn in typestr.split(',')]
  return list(set([APN_TYPE_MAP[t] for t in typelist if t]))


APN_PROTOCOL_MAP = {
    'ip': carrier_settings_pb2.ApnItem.IP,
    'ipv4': carrier_settings_pb2.ApnItem.IP,
    'ipv6': carrier_settings_pb2.ApnItem.IPV6,
    'ipv4v6': carrier_settings_pb2.ApnItem.IPV4V6,
    'ppp': carrier_settings_pb2.ApnItem.PPP
}

BOOL_MAP = {'true': True, 'false': False, '1': True, '0': False}

APN_SKIPXLAT_MAP = {
    -1: carrier_settings_pb2.ApnItem.SKIP_464XLAT_DEFAULT,
    0: carrier_settings_pb2.ApnItem.SKIP_464XLAT_DISABLE,
    1: carrier_settings_pb2.ApnItem.SKIP_464XLAT_ENABLE
}

# not include already handeld string keys like mcc, protocol
APN_STRING_KEYS = [
    'bearer_bitmask', 'server', 'proxy', 'port', 'user', 'password', 'mmsc',
    'mmsc_proxy', 'mmsc_proxy_port'
]

# keys that are different between apn.xml and apn.proto
APN_REMAP_KEYS = {
    'mmsproxy': 'mmsc_proxy',
    'mmsport': 'mmsc_proxy_port'
}

APN_INT_KEYS = [
    'authtype', 'mtu', 'profile_id', 'max_conns', 'wait_time', 'max_conns_time'
]

APN_BOOL_KEYS = [
    'modem_cognitive', 'user_visible', 'user_editable'
]


def gen_apnitem(node):
  """Create ApnItem proto based on APN node from xml file.

  Args:
    node: xml dom node from apn conf xml file.

  Returns:
    An ApnItem proto.
  """
  apn = carrier_settings_pb2.ApnItem()
  apn.name = node.getAttribute('carrier')
  apn.value = node.getAttribute('apn')
  apn.type.extend(map_apntype(node.getAttribute('type')))
  for key in ['protocol', 'roaming_protocol']:
    if node.hasAttribute(key):
      setattr(apn, key, APN_PROTOCOL_MAP[node.getAttribute(key).lower()])

  for key in node.attributes.keys():
    # Treat bearer as bearer_bitmask if no bearer_bitmask specified
    if key == 'bearer' and not node.hasAttribute('bearer_bitmask'):
      setattr(apn, 'bearer_bitmask', node.getAttribute(key))
      continue
    if key == 'skip_464xlat':
      setattr(apn, key, APN_SKIPXLAT_MAP[int(node.getAttribute(key))])
      continue
    if key in APN_STRING_KEYS:
      setattr(apn, key, node.getAttribute(key))
      continue
    if key in APN_REMAP_KEYS:
      setattr(apn, APN_REMAP_KEYS[key], node.getAttribute(key))
      continue
    if key in APN_INT_KEYS:
      setattr(apn, key, int(node.getAttribute(key)))
      continue
    if key in APN_BOOL_KEYS:
      setattr(apn, key, BOOL_MAP[node.getAttribute(key).lower()])
      continue

  return apn


def main():
  known = get_knowncarriers([FLAGS.data_dir + '/' + f for f in CARRIER_LISTS])

  with open(FLAGS.apn_file, 'r', encoding='utf-8') as apnfile:
    dom = minidom.parse(apnfile)

  apn_map = collections.defaultdict(list)
  for apn_node in dom.getElementsByTagName('apn'):
    cname = get_cname(gen_cid(apn_node), known)
    apn = gen_apnitem(apn_node)
    apn_map[cname].append(apn)

  mcs = carrier_settings_pb2.MultiCarrierSettings()
  for c in apn_map:
    carriersettings = mcs.setting.add()
    carriersettings.canonical_name = c
    carriersettings.apns.apn.extend(apn_map[c])

  with open(FLAGS.out_file, 'w', encoding='utf-8') as apnout:
    apnout.write(text_format.MessageToString(mcs, as_utf8=True))


if __name__ == '__main__':
  main()
