/*
 * Copyright (C) 2018 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
 */

package com.android.tools.build.bundletool.device.activitymanager;

import com.android.tools.build.bundletool.device.activitymanager.PatternConfigQualifierParser.MccParser;
import com.android.tools.build.bundletool.device.activitymanager.PatternConfigQualifierParser.MncParser;
import com.google.common.collect.ImmutableList;

/** Parsing functions for resource config string generated by the Activity Manager shell command. */
public class ResourceConfigParser {

  /** Describes ability to parse the qualifier in the resource string. */
  interface ConfigQualifierParser<T> {

    /**
     * Returns whether parsing was successful. Note, that parsing can be unsuccessful because the
     * qualifier of a given type wasn't present.
     */
    boolean parse(ConfigStringIterator iterator, ResourceConfigHandler<T> handler);
  }

  /** Parses the whole resource config string representing the device configuration. */
  public static <T> T parseDeviceConfig(String configString, ResourceConfigHandler<T> handler) {
    ConfigStringIterator iterator = new ConfigStringIterator(configString);

    if (!iterator.hasNext()) {
      return handler.getOutput();
    }
    iterator.next();

    // Parsers of the qualifiers of the resource config string. The order is significant.
    // We are interested only in the locale so we skip parsing beyond that qualifier.

    ImmutableList<ConfigQualifierParser<T>> configQualifierParsers =
        ImmutableList.of(new MccParser<>(), new MncParser<>(), new LocaleParser<>());

    for (ConfigQualifierParser<T> parser : configQualifierParsers) {
      if (parser.parse(iterator, handler)) {
        // We only advance the iterator if we successfully identified and parsed a given qualifier.
        if (!iterator.hasNext()) {
          return handler.getOutput();
        }
        iterator.next();
      }
    }

    // Normally we would detect an error input here. If after all qualifier parsers tried to parse
    // the input, we are still not at the end of the string, the string is invalid. But, we are
    // likely not to be at the end of string becacuse we skipped all parsers beyond locale
    // qualifier.

    return handler.getOutput();
  }

  /** Handler of the parsed resource string fragments. */
  public interface ResourceConfigHandler<T> {

    default void onMccCode(int mccCode) {}

    default void onMncCode(int mncCode) {}

    /** Can be called multiple times. */
    default void onLocale(String locale) {}

    T getOutput();
  }
}
