#!/usr/bin/env python
#
# Copyright (C) 2019 The Android Open Source Project
#
# 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.


import argparse
import collections
import json
import sys

def follow_path(obj, path):
  cur = obj
  last_key = None
  for key in path.split('.'):
    if last_key:
      if last_key not in cur:
        return None,None
      cur = cur[last_key]
    last_key = key
  if last_key not in cur:
    return None,None
  return cur, last_key


def ensure_path(obj, path):
  cur = obj
  last_key = None
  for key in path.split('.'):
    if last_key:
      if last_key not in cur:
        cur[last_key] = dict()
      cur = cur[last_key]
    last_key = key
  return cur, last_key


class SetValue(str):
  def apply(self, obj, val):
    cur, key = ensure_path(obj, self)
    cur[key] = val


class Replace(str):
  def apply(self, obj, val):
    cur, key = follow_path(obj, self)
    if cur:
      cur[key] = val


class ReplaceIfEqual(str):
  def apply(self, obj, old_val, new_val):
    cur, key = follow_path(obj, self)
    if cur and cur[key] == int(old_val):
      cur[key] = new_val


class Remove(str):
  def apply(self, obj):
    cur, key = follow_path(obj, self)
    if cur:
      del cur[key]


class AppendList(str):
  def apply(self, obj, *args):
    cur, key = ensure_path(obj, self)
    if key not in cur:
      cur[key] = list()
    if not isinstance(cur[key], list):
      raise ValueError(self + " should be a array.")
    cur[key].extend(args)

# A JSONDecoder that supports line comments start with //
class JSONWithCommentsDecoder(json.JSONDecoder):
  def __init__(self, **kw):
    super().__init__(**kw)

  def decode(self, s: str):
    s = '\n'.join(l for l in s.split('\n') if not l.lstrip(' ').startswith('//'))
    return super().decode(s)

def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('-o', '--out',
                      help='write result to a file. If omitted, print to stdout',
                      metavar='output',
                      action='store')
  parser.add_argument('input', nargs='?', help='JSON file')
  parser.add_argument("-v", "--value", type=SetValue,
                      help='set value of the key specified by path. If path doesn\'t exist, creates new one.',
                      metavar=('path', 'value'),
                      nargs=2, dest='patch', default=[], action='append')
  parser.add_argument("-s", "--replace", type=Replace,
                      help='replace value of the key specified by path. If path doesn\'t exist, no op.',
                      metavar=('path', 'value'),
                      nargs=2, dest='patch', action='append')
  parser.add_argument("-se", "--replace-if-equal", type=ReplaceIfEqual,
                      help='replace value of the key specified by path to new_value if it\'s equal to old_value.' +
                      'If path doesn\'t exist or the value is not equal to old_value, no op.',
                      metavar=('path', 'old_value', 'new_value'),
                      nargs=3, dest='patch', action='append')
  parser.add_argument("-r", "--remove", type=Remove,
                      help='remove the key specified by path. If path doesn\'t exist, no op.',
                      metavar='path',
                      nargs=1, dest='patch', action='append')
  parser.add_argument("-a", "--append_list", type=AppendList,
                      help='append values to the list specified by path. If path doesn\'t exist, creates new list for it.',
                      metavar=('path', 'value'),
                      nargs='+', dest='patch', default=[], action='append')
  args = parser.parse_args()

  if args.input:
    with open(args.input) as f:
      obj = json.load(f, object_pairs_hook=collections.OrderedDict, cls=JSONWithCommentsDecoder)
  else:
    obj = json.load(sys.stdin, object_pairs_hook=collections.OrderedDict, cls=JSONWithCommentsDecoder)

  for p in args.patch:
    p[0].apply(obj, *p[1:])

  if args.out:
    with open(args.out, "w") as f:
      json.dump(obj, f, indent=2, separators=(',', ': '))
      f.write('\n')
  else:
    print(json.dumps(obj, indent=2, separators=(',', ': ')))


if __name__ == '__main__':
  main()
