/*
 * Copyright (C) 2015 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.car;

import android.car.test.CarTestManager;
import android.car.test.ICarTest;
import android.content.Context;
import android.os.IBinder;
import android.util.Log;

import com.android.car.hal.VehicleHal;
import com.android.car.vehiclenetwork.IVehicleNetworkHalMock;
import com.android.car.vehiclenetwork.VehicleNetwork;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
import com.android.car.vehiclenetwork.VehiclePropValueParcelable;

import java.io.PrintWriter;
import java.util.NoSuchElementException;

/**
 * Service to allow testing / mocking vehicle HAL.
 * This service uses Vehicle HAL APIs directly (one exception) as vehicle HAL mocking anyway
 * requires accessing that level directly.
 */
public class CarTestService extends ICarTest.Stub implements CarServiceBase {

    private final Context mContext;
    private final VehicleNetwork mVehicleNetwork;
    private final ICarImpl mICarImpl;
    private boolean mInMocking = false;
    private int mMockingFlags = 0;
    private Exception mException = null;
    private IVehicleNetworkHalMock mMock = null;
    private final MockDeathRecipient mDeathRecipient = new MockDeathRecipient();

    public CarTestService(Context context, ICarImpl carImpl) {
        mContext = context;
        mICarImpl = carImpl;
        mVehicleNetwork = VehicleHal.getInstance().getVehicleNetwork();
    }

    @Override
    public void init() {
        // nothing to do.
        // This service should not reset anything for init / release to maintain mocking.
    }

    @Override
    public void release() {
        // nothing to do
        // This service should not reset anything for init / release to maintain mocking.
    }

    @Override
    public void dump(PrintWriter writer) {
        writer.println("*CarTestService*");
        writer.println(" mInMocking:" + mInMocking);
    }

    @Override
    public void injectEvent(VehiclePropValueParcelable value) {
        ICarImpl.assertVehicleHalMockPermission(mContext);
        mVehicleNetwork.injectEvent(value.value);
    }

    @Override
    public void startMocking(final IVehicleNetworkHalMock mock, final int flags) {
        ICarImpl.assertVehicleHalMockPermission(mContext);
        CarServiceUtils.runOnMainSync(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (this) {
                        mInMocking = true;
                        mMockingFlags = flags;
                        mException = null;
                        if (mMock != null) {
                            Log.w(CarLog.TAG_TEST,
                                    "New mocking started while previous one is not stopped");
                            try {
                                mMock.asBinder().unlinkToDeath(mDeathRecipient, 0);
                            } catch (NoSuchElementException e) {
                                //ignore
                            }
                        }
                        mMock = mock;
                    }
                    mock.asBinder().linkToDeath(mDeathRecipient, 0);
                    mVehicleNetwork.startMocking(mock);
                    mICarImpl.startMocking();
                } catch (Exception e) {
                    Log.w(CarLog.TAG_TEST, "startMocking failed", e);
                    synchronized (this) {
                        mException = e;
                        mInMocking = false;
                        mMockingFlags = 0;
                    }
                }
                Log.i(CarLog.TAG_TEST, "start vehicle HAL mocking, flags:0x" +
                        Integer.toHexString(flags));
            }
        });
        synchronized (this) {
            if (mException != null) {
                throw new IllegalStateException(mException);
            }
        }
    }

    @Override
    public void stopMocking(final IVehicleNetworkHalMock mock) {
        ICarImpl.assertVehicleHalMockPermission(mContext);
        CarServiceUtils.runOnMainSync(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (this) {
                        if (!mInMocking) {
                            throw new IllegalStateException("not in mocking");
                        }
                        if (mMock.asBinder() != mock.asBinder()) {
                            throw new IllegalArgumentException("Try to stop mocking not owned");
                        }
                        try {
                            mMock.asBinder().unlinkToDeath(mDeathRecipient, 0);
                        } catch (NoSuchElementException e) {
                            //ignore
                        }
                    }
                    mVehicleNetwork.stopMocking(mock);
                    mICarImpl.stopMocking();
                    synchronized (this) {
                        mInMocking = false;
                        mMockingFlags = 0;
                        mException = null;
                        mMock = null;
                    }
                    Log.i(CarLog.TAG_TEST, "stop vehicle HAL mocking");
                } catch (Exception e) {
                    Log.w(CarLog.TAG_TEST, "stopMocking failed", e);
                }
            }
        });
    }

    @Override
    public boolean isPropertySupported(int property) {
        VehiclePropConfigs configs = VehicleHal.getInstance().getVehicleNetwork().listProperties(
                property);
        return configs != null;
    }

    public synchronized boolean isInMocking() {
        return mInMocking;
    }

    public synchronized boolean shouldDoRealShutdownInMocking() {
        return (mMockingFlags & CarTestManager.FLAG_MOCKING_REAL_SHUTDOWN) != 0;
    }

    private class MockDeathRecipient implements IBinder.DeathRecipient {
        @Override
        public void binderDied() {
            CarServiceUtils.runOnMainSync(() -> {
               try {
                   IVehicleNetworkHalMock mock;
                   synchronized (this) {
                       mock = mMock;
                   }
                   stopMocking(mock);
               } catch (Exception e) {
                   //ignore
               }
            });
        }
    }
}
